@import url('https://fonts.googleapis.com/css2?family=Mulish:wght@300;400;500;600;700;800&display=swap');
/* vanillajs-datepicker base CSS, loaded via the always-present operator stylesheet so the calendar grid
   survives SPA navigation (the SPA swaps <main> + re-runs scripts but does NOT add <head> <link>s). */
@import url('https://cdn.jsdelivr.net/npm/vanillajs-datepicker@1.3.4/dist/css/datepicker.min.css');
/* freight-sans-pro — Fusion Students' body face, loaded from their own Adobe Fonts (Typekit) kit
   (same kit the fusionstudents.co.uk site uses). Not self-hostable (licensed); falls back to Mulish
   if the kit doesn't serve to this domain. */
@import url('https://use.typekit.net/xrm2jcx.css');

/* Rotonto — Fusion Students' custom display face. Self-hosted from /assets/fonts/. */
@font-face {
  font-family: 'Rotonto';
  src: url('/assets/fonts/Rotonto-Regular.woff') format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Hex values lifted directly from fusionstudents.co.uk so brand greens,
     rust buttons, and sage tags match the canonical site exactly. */
  --brand: #37543b;
  --brand-dark: #243a27;
  --button: #a14d3d;
  --button-dark: #813c30;
  --tag-bg: #bdbd89;
  /* Secondary Fusion accents — drive the property-map category colours
     (COOL blue for retail/transport, WARM orange for food & drink).
     Rust (--button) is reserved exclusively for the building pin. */
  --accent-cool: #85abd4;
  --accent-warm: #ff7844;
  --ink: #37543b;
  --paper: #fdfbf7;
  --line: #d6d3c9;
  --bs-primary: #37543b;
  --bs-primary-rgb: 55, 84, 59;
  /* Square corners across the board — Bootstrap's components inherit these. */
  --bs-border-radius: 0;
  --bs-border-radius-sm: 0;
  --bs-border-radius-lg: 0;
  --bs-border-radius-xl: 0;
  --bs-border-radius-2xl: 0;
  --bs-border-radius-pill: 0;

  /* ---- Type scale: single source of truth for UI font sizes (1rem = 17px base). ----
     Use var(--fs-*) for ALL interface text. Raw px / off-scale rem are reserved for
     print documents (contracts, emails, PDFs), never UI chrome. */
  --wv-fp-match: var(--accent-warm, #ff7844); /* social/match accent = brand warm accent */
  --fs-2xs: 0.7rem;
  --fs-xs: 0.8rem;
  --fs-sm: 0.9rem;
  --fs-base: 1rem;
  --fs-md: 1.15rem;
  --fs-lg: 1.4rem;
  --fs-xl: 1.8rem;
  --fs-2xl: 2.2rem;
  --fs-3xl: 2.75rem;
  --fs-hero: clamp(1.75rem, 3vw, 2.75rem);
  --fs-hero-sm: clamp(1.3rem, 2.4vw, 1.9rem);

  /* Distance from the viewport's right (or left) edge to the page content's edge — i.e. main's centred
     1280px column plus its padding. Anchor viewport-fixed UI (chat launcher/panel) here so they line up
     with the content gutter instead of bleeding to the screen edge. */
  --wv-page-gutter: calc(max(0px, (100vw - 1280px) / 2) + clamp(1rem, 3vw, 2.5rem));
}

/* Catch-all for any component with a hard-coded border-radius. */
* { border-radius: 0 !important; }

/* All buttons get the Fusion treatment: uppercase, tight tracking, semibold. */
.btn, button.btn-primary, button[type="submit"] {
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 600;
  font-size: var(--fs-sm);
}

/* Bootstrap 5 buttons use scoped CSS variables. Theming btn-primary requires
 * overriding all the per-state vars explicitly. */
.btn-primary {
  --bs-btn-bg: var(--button);
  --bs-btn-border-color: var(--button);
  --bs-btn-hover-bg: var(--button-dark);
  --bs-btn-hover-border-color: var(--button-dark);
  --bs-btn-active-bg: var(--button-dark);
  --bs-btn-active-border-color: var(--button-dark);
  --bs-btn-disabled-bg: var(--button);
  --bs-btn-disabled-border-color: var(--button);
  --bs-btn-focus-shadow-rgb: 151, 79, 62;
}
.btn-outline-primary {
  --bs-btn-color: var(--button);
  --bs-btn-border-color: var(--button);
  --bs-btn-hover-bg: var(--button);
  --bs-btn-hover-border-color: var(--button);
  --bs-btn-active-bg: var(--button-dark);
  --bs-btn-active-border-color: var(--button-dark);
  --bs-btn-focus-shadow-rgb: 151, 79, 62;
}

/* Form check (checkbox / radio) — checked + focus states. */
.form-check-input:checked {
  background-color: var(--brand);
  border-color: var(--brand);
}
.form-check-input:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 0.25rem rgba(161, 77, 61, 0.25);
}

/* Text inputs / selects — pink focus halo instead of Bootstrap's blue. */
.form-control:focus,
.form-select:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 0.25rem rgba(161, 77, 61, 0.25);
}

/* Info banners — branded sage-green instead of Bootstrap's cyan alert-info. */
.alert-info {
  --bs-alert-color: var(--brand-dark);
  --bs-alert-bg: rgba(55, 84, 59, 0.08);
  --bs-alert-border-color: rgba(55, 84, 59, 0.25);
  --bs-alert-link-color: var(--brand-dark);
}

/* Bootstrap accordion (FAQ) — pink active state instead of default blue. */
.accordion-button:not(.collapsed) {
  color: var(--brand-dark);
  background-color: rgba(161, 77, 61, 0.08);
  box-shadow: inset 0 -1px 0 rgba(161, 77, 61, 0.2);
}
.accordion-button:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 0.25rem rgba(161, 77, 61, 0.20);
}
.wv-faq-icon { margin-right: 0.6rem; color: var(--brand); }
.accordion-button:not(.collapsed) .wv-faq-icon { color: var(--brand-dark); }

html {
  /* 17px base, absolute on purpose — must NOT be a rem token: var(--fs-base)=1rem is self-referential
     on the root and collapses to the browser default 16px, shrinking every rem on the page. fs-allow */
  font-size: 17px;
  /* Standard browser scrollbar, always shown (overflow-y: scroll) so pages that do / don't overflow
     don't shift the layout sideways (the "jangle" between pages). */
  overflow-y: scroll;
  background: #E3E3D9;
}
body {
  font-family: 'freight-sans-pro', 'Mulish', "Century Gothic", "Calibri", Arial, "Helvetica Neue", Helvetica, sans-serif;
  color: var(--ink);
  background: #E3E3D9;
  line-height: 1.5;
  /* Sticky-footer scaffold: body is a flex column, main grows to fill the
     viewport so any appended footer (trust strip) ends up at the bottom on
     short pages. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin: 0;
}

main { max-width: 1280px; margin: 1rem auto 3rem; padding: 0 clamp(1rem, 3vw, 2.5rem); flex: 1 0 auto; width: 100%; box-sizing: border-box; display: flex; flex-direction: column; }
/* When the page has a full-bleed hero, drop main's top margin so the hero
   sits flush under the navbar (no cream strip showing through). */
main:has(> .hero), main:has(> #hero) { margin-top: 0; }
/* On cascade pages (city/building/rooms/tenancy) the hero is full-bleed and
   should sit directly beneath the navbar; the breadcrumb belongs underneath
   it on the cream page background. Pages without a .hero are unaffected
   because only #breadcrumb gets an explicit order. */
main > .hero, main > #hero { order: -3; }
main > .wv-building-nav { order: -2; }
main > #breadcrumb { order: -1; }

/* Headings — Rotonto, uppercase, brand green. Lifted from fusionstudents.co.uk's
   own treatment so this operator's pages read as clearly "Fusion" at a glance. */
h1, h2, h3, h4, h5, h6, .wv-brand {
  font-family: 'Rotonto', 'Mulish', "Century Gothic", system-ui, sans-serif;
  font-weight: 400;
  text-transform: uppercase;
  line-height: 1.25;
  color: var(--brand);
  letter-spacing: 0.01em;
}
h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-lg); margin-top: 1.75rem; }
h3 { font-size: var(--fs-md); }

a { color: var(--brand); text-decoration: none; }
a:hover { color: var(--brand-dark); }

/* WookiVerse branding — only "Verse" is bold */
.wv-brand b { font-weight: 700; }
.wv-brand {
  color: var(--ink);
  font-weight: normal;
  font-size: var(--fs-lg);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
}
.wv-brand:hover { color: var(--ink); text-decoration: none; }
.wv-brand-logo { height: 40px; width: auto; display: block; }

/* Demo-scenario picker on the brand. The logo stays a plain home link;
 * the "WookiVerse Demo" text is the trigger button for the dropdown. */
/* Brand sits left at its natural width; the search is absolutely centred over the bar, so the brand can
   never be squeezed or overlapped by it. */
.wv-brand-wrap { position: relative; display: inline-flex; align-items: center; gap: 0.6rem; flex: 0 0 auto; min-width: 0; }
.wv-brand-home { display: inline-flex; align-items: center; }
.wv-brand-trigger {
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 0.2rem 0.4rem;
  border-radius: 0.4rem;
  font-family: inherit;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.wv-brand-trigger:hover { background: rgba(0, 0, 0, 0.03); }
.wv-brand-caret { font-size: var(--fs-xs); color: #999; transition: transform 0.15s; }
.wv-brand-trigger[aria-expanded="true"] .wv-brand-caret { transform: rotate(180deg); }
.wv-scenario-badge {
  background: var(--brand);
  color: white;
  font-size: var(--fs-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.15rem 0.5rem;
  border-radius: 0.7rem;
}
/* Bootstrap dropdown panel — toggled via .show class. */
.wv-scenario-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 0.4rem;
  min-width: 280px;
  list-style: none;
  padding: 0.4rem 0;
  background: white;
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.10);
  z-index: 200;
}
.wv-scenario-menu.show { display: block; }
.wv-scenario-menu .dropdown-header {
  padding: 0.4rem 1rem 0.3rem;
  margin: 0;
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #999;
}
.wv-scenario-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 0.55rem 1rem;
  cursor: pointer;
  font-family: inherit;
  font-size: var(--fs-sm);
  color: var(--ink);
}
.wv-scenario-item:hover, .wv-scenario-item:focus {
  background: rgba(161, 77, 61, 0.08);
  color: var(--brand-dark);
}
.wv-scenario-item.is-active {
  background: rgba(161, 77, 61, 0.12);
}
.wv-scenario-item.is-active strong::before {
  content: '✓ ';
  color: var(--brand);
}

/* Top chrome (signed-in / signed-out header) */
#wv-chrome {
  /* Pinned to the top so search + nav stay reachable while scrolling long room/contract pages. */
  position: sticky;
  top: 0;
  z-index: 1030;
  background: #3C543A;
  border-bottom: 1px solid rgba(0,0,0,0.15);
  padding: 0.9rem 1rem;
  /* Reserve the bar's rendered height (40px logo + 0.9rem×2 padding) so it doesn't shift the
     page down when chrome.js fills it in. */
  box-sizing: border-box;
  min-height: calc(40px + 1.8rem);
}
/* Brand-trigger "DEMO" label — Rotonto, generous size, in white to sit as
   a quiet accent next to the logo. */
#wv-chrome .wv-brand-trigger,
#wv-chrome .wv-brand-trigger > span {
  font-family: 'Rotonto', 'Mulish', "Century Gothic", system-ui, sans-serif;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: var(--fs-xl);
  color: #fff;
}
#wv-chrome .wv-brand-caret { color: #fff; font-size: var(--fs-base); }
#wv-chrome .wv-brand,
#wv-chrome .wv-brand-trigger,
#wv-chrome .wv-brand:hover,
#wv-chrome .wv-chrome-right,
#wv-chrome .wv-greeting,
#wv-chrome .wv-signout,
#wv-chrome .wv-search-trigger,
#wv-chrome .wv-user-icon { color: #fff; }
/* Brand left · search absolutely centred over the bar · user right. Absolute centring keeps the search
   at true viewport centre regardless of the brand/user widths; the constant side clearance baked into the
   input width (below) guarantees it never reaches the brand or the account block. */
.wv-chrome-search { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); display: flex; justify-content: center; z-index: 1; }
#wv-chrome .wv-search-input { color: #fff; border: 1px solid rgba(255,255,255,0.85); border-right: 0; background: transparent; }
/* The rust button carries the outline on the three non-seam sides so input+button read as one pill. */
#wv-chrome .wv-search-trigger { border: 1px solid rgba(255,255,255,0.85); border-left: 0; }
#wv-chrome .wv-search-input::placeholder { color: rgba(255,255,255,0.7); }
.wv-chrome-inner { max-width: none; margin: 0; padding: 0 clamp(1rem, 3vw, 2.5rem); display: flex; justify-content: space-between; align-items: center; position: relative; }
.wv-chrome-right { font-size: var(--fs-base); color: #fff; flex: 0 0 auto; display: flex; align-items: center; justify-content: flex-end; min-width: 0; }
.wv-greeting { margin-right: 1rem; color: #fff; }
.wv-signout { color: rgba(255,255,255,0.75); font-size: var(--fs-sm); }

/* Resume banner dismiss — same pink-circle treatment as the activity-toast
 * close button, perched on the banner's top-right corner. */
.wv-resume-dismiss {
  position: absolute;
  top: -0.5rem;
  right: -0.5rem;
  background: var(--button);
  border: 2px solid white;
  border-radius: 50%;
  width: 24px;
  height: 24px;
  font-size: var(--fs-xs);
  line-height: 1;
  color: white;
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
  transition: background 0.15s, transform 0.15s;
}
.wv-resume-dismiss:hover { background: var(--button-dark, #883f31); transform: scale(1.08); }
.resume-banner { position: relative; }

/* Card grid */
.card { background: #fff; border-color: var(--line); }
.card-img-top { height: 180px; object-fit: cover; }

/* Country flags — circular PNGs from the backend's flag pack.
 *   .wv-flag             inline (e.g. next to country name)
 *   .wv-flag-lg          larger size variant
 *   .wv-country-hero     wraps the country card photo + overlay flag
 *   .wv-flag-overlay     circular flag perched on the photo's bottom-left */
.wv-flag    { width: 2rem; height: 2rem; border-radius: 50%; object-fit: cover; flex: 0 0 auto; vertical-align: middle; }
.wv-flag-lg { width: 3rem; height: 3rem; }
/* Country card body — title on the left, circular flag on the right. */
.wv-country-body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
/* Country page H1 — flag on the left, country name to the right of it. */
.wv-country-title {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}
.wv-country-flag {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--line);
  flex: 0 0 auto;
}

/* Profile page */
.wv-profile-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 0.9rem;
  padding: 1rem 1.25rem;
  margin: 1rem 0 1.5rem;
}
.wv-profile-avatar { font-size: var(--fs-3xl); color: var(--brand); }
.wv-profile-name { font-size: var(--fs-md); font-weight: 600; color: var(--ink); }
.wv-section-icon { color: var(--brand); margin-right: 0.4rem; }
.wv-status-pill {
  display: inline-block;
  padding: 0.25rem 0.7rem;
  border-radius: 1rem;
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-top: auto;
  align-self: flex-start;
}
.wv-status-current  { background: rgba(161, 77, 61, 0.10); color: var(--brand-dark); }
.wv-status-upcoming { background: #e7f3fe; color: #0a66c2; }
.wv-status-past     { background: #f1f1f1; color: #6b6b6b; }

/* Hero */
/* Full-bleed cinematic hero — image fills, text overlays in white with a
   left-side gradient mask for legibility. Matches the Fusion treatment on
   their property pages. */
.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: clamp(300px, 36vw, 460px);
  margin: 0 calc(-50vw + 50%) 2rem;
  width: 100vw;
  overflow: hidden;
}
.hero > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  z-index: 0;
}
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.2) 55%, rgba(0,0,0,0) 100%);
  pointer-events: none;
  z-index: 1;
}
.hero-text {
  position: relative;
  z-index: 2;
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 clamp(1rem, 3vw, 2.5rem);
  color: #fff;
  width: 100%;
}
.hero-text h1 { color: #fff; font-size: var(--fs-hero); margin-bottom: 0.6rem; }
.hero-text p {
  color: #fff; max-width: 580px; margin-top: 1.1rem;
  font-size: var(--fs-md); line-height: 1.6; font-weight: 400; opacity: 0.96;
}
/* Address line under the building name, above the strapline. Muted white over the hero image,
   icon in the operator accent. */
.wv-hero-address {
  display: flex; align-items: center; gap: 0.5rem;
  color: #fff; opacity: 0.95; margin: 0.4rem 0 0;
  font-size: var(--fs-md); font-weight: 500; letter-spacing: 0.01em; line-height: 1.55;
}
.wv-hero-address i { color: var(--button); opacity: 1; }

/* Hero CTAs — pinned to the bottom-right of the text column, level with the tagline. */
#hero-cta {
  position: absolute; z-index: 3; bottom: 0; right: clamp(1rem, 3vw, 2.5rem); margin: 0; padding: 0;
}
@media (max-width: 640px) {
  #hero-cta { position: static; right: auto; margin: 1.25rem 0 0; }
}

/* Buttons — operator accent (rust). */
.btn-primary {
  background-color: var(--button);
  border-color: var(--button);
}
.btn-primary:hover, .btn-primary:focus {
  background-color: var(--button-dark);
  border-color: var(--button-dark);
}
.btn-outline-primary {
  color: var(--button);
  border-color: var(--button);
}
.btn-outline-primary:hover, .btn-outline-primary:focus, .btn-check:checked + .btn-outline-primary {
  background-color: var(--button);
  border-color: var(--button);
  color: white;
}

/* Sold-out / unavailable options: faded so the page isn't blank and the user sees "you missed it". */
.wv-unavailable { opacity: 0.6; filter: grayscale(0.3); }
.wv-sold-badge { align-self: flex-start; }

/* Tag chips */
.wv-tags { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.5rem; }
.wv-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: var(--tag-bg);
  border: 1px solid var(--line);
  color: #3C543A;
  padding: 0.2rem 0.55rem;
  border-radius: 0;
  font-size: var(--fs-xs);
}
.wv-tag i { color: var(--brand); }
/* Desired-but-missing criteria: a pale-orange tag with a diagonal slash (the room lacks it). The icon
   keeps the criterion's own glyph; the slash conveys "not available". */
.wv-tags-miss { margin-top: 0.25rem; }
.wv-tag-miss {
  position: relative;
  background: #fbede9;
  color: #813c30;
  border-color: #e8c5b8;
}
.wv-tag-miss i { color: #a14d3d; }
/* Two crossing diagonals = an X over the tag (clearer "crossed out" than a single slash). */
.wv-tag-miss::before,
.wv-tag-miss::after {
  content: '';
  position: absolute;
  left: 4px; right: 4px; top: 50%;
  border-top: 2px solid rgba(129, 60, 48, 0.65);
  pointer-events: none;
}
.wv-tag-miss::before { transform: rotate(7deg); }
.wv-tag-miss::after  { transform: rotate(-7deg); }
/* Inline price delta beside the £/wk, in the same orange (a saving stays green). */
.wv-price-delta {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.05rem 0.4rem;
  background: #fbede9;
  color: #813c30;
  border: 1px solid #e8c5b8;
  font-size: var(--fs-xs);
  font-weight: 600;
  vertical-align: middle;
}
.wv-price-delta.wv-price-save {
  background: #e7f0e4;
  color: #2e5d2a;
  border-color: #c4dabd;
}

/* Context bar (step pages) */
.context-bar {
  background: var(--brand);
  color: white;
  padding: 0.6rem 1rem;
  border-radius: 6px;
  margin-bottom: 1.5rem;
  font-size: var(--fs-base);
  /* Hidden for now on every page (the basket card carries the context + hold countdown). Remove this
     line to bring the green booking bar back. */
  display: none;
}

/* Resume banner (index.html) */
.resume-banner {
  background: #fbede9;
  border: 1px solid var(--brand);
  color: var(--brand-dark);
  padding: 1rem;
  border-radius: 8px;
  margin-bottom: 1.5rem;
}
/* Full-height thumbnail of the chosen room, flush to the banner's left edge. Its own
   rounded left corners match the banner (no overflow:hidden on the banner, so the
   absolutely-positioned close button in the corner isn't clipped). */
.resume-banner .resume-thumb {
  flex: 0 0 auto; align-self: stretch; aspect-ratio: 16 / 9;
  margin: -1rem 0 -1rem -1rem; /* cancel the banner padding on top/bottom/left */
  border-radius: 7px 0 0 7px;
  background-size: cover; background-position: center;
}
.resume-banner .resume-hold { color: var(--button); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Reserve a fixed width for just the ticking time ("mm:ss"), so the button sits right after it and can't
   wobble as the digits change (the font doesn't honour tabular-nums). "Booking held for" is static text. */
.resume-banner #resume-cd { display: inline-block; min-width: 4.2em; }
.resume-banner .resume-extend {
  margin-left: 8px;
  display: inline-block; color: var(--button); background: transparent;
  border: 1px solid var(--button); border-radius: 6px; padding: 2px 11px;
  font-weight: 600; text-decoration: none; text-transform: uppercase; letter-spacing: 0.06em; font-size: var(--fs-2xs);
}
.resume-banner .resume-extend:hover { background: var(--button); color: #fff; text-decoration: none; }

/* Misc */
iframe { border: 1px solid var(--line); border-radius: 6px; }
.muted { color: #888; font-size: var(--fs-base); }
.error { color: #c00; }

.fake-card-form {
  display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0.5rem; max-width: 500px; margin: 1rem 0;
}
.fake-card-form input { width: 100%; }
.fake-card-form input.full { grid-column: 1 / -1; }

/* Filter bar row: the (shortened) chip bar on the left + the standalone Period
 * box on the right. The chip bar flexes to fill; the period box hugs the right. */
.wv-filterbar-row { display: flex; align-items: stretch; gap: 0.5rem; margin-bottom: 1rem; }
.wv-filterbar-row .wv-chipbar { flex: 1 1 auto; min-width: 0; margin-bottom: 0; }

/* Period selector — a distinct white rectangle, visually separate from the filters. */
.wv-period-box {
  position: relative;
  flex: 0 0 auto;
  margin-left: auto;
  display: flex;
  align-items: center;
  background: #fff;
  border: 1px solid #ece3e8;
  border-radius: 14px;
  padding: 0.3rem 0.4rem;
  min-height: 52px;
}
.wv-period-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border: 1px solid #e0d3da;
  border-radius: 999px;
  background: #fff;
  color: var(--brand-dark);
  cursor: pointer;
  padding: 0.4rem 0.85rem;
  font-size: var(--fs-sm);
  white-space: nowrap;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.wv-period-toggle:hover { border-color: var(--brand); color: var(--brand); }
.wv-period-caption {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #9a8a93;
}
.wv-period-current { font-weight: 600; }
.wv-period-caret { font-size: var(--fs-2xs); transition: transform 0.15s ease; }
.wv-period-box.is-open .wv-period-caret { transform: rotate(180deg); }
.wv-period-menu {
  position: absolute;
  top: calc(100% + 0.3rem);
  right: 0;
  z-index: 30;
  margin: 0;
  padding: 0.3rem;
  list-style: none;
  min-width: 100%;
  background: #fff;
  border: 1px solid #ece3e8;
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}
.wv-period-menu[hidden] { display: none; }
.wv-period-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
  border: 0;
  background: transparent;
  border-radius: 8px;
  padding: 0.45rem 0.7rem;
  font-size: var(--fs-sm);
  color: var(--brand-dark);
  cursor: pointer;
  white-space: nowrap;
}
.wv-period-item:hover { background: #f6eef3; }
.wv-period-item.is-selected { color: var(--brand); font-weight: 600; }

/* Thin always-on filter chip bar. ONE slim row: left arrow · scrolling groups
 * (ALL-CAPS header + chips, divided) · right arrow, with a right-edge fade
 * hinting overflow. No expand/collapse, no Apply — chips apply live on tap.
 * Squared Fusion language. */
.wv-chipbar {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  margin-bottom: 1rem;
  background: #fff;
  border: 1px solid #e2e2e2;
  border-radius: 2px;
  padding: 0.3rem 0.4rem;
}
.wv-chipbar-row { display: flex; align-items: stretch; gap: 0.4rem; min-height: 46px; min-width: 0; }
.wv-chipbar-row[hidden] { display: none; }
.wv-chipbar-row[data-row="2"]:not([hidden]) { border-top: 1px solid #ececec; margin-top: 0.3rem; padding-top: 0.3rem; }
.wv-chipbar-arrow {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  border: 1px solid #d6d6d6;
  border-radius: 2px;
  background: #fff;
  color: var(--brand-dark);
  cursor: pointer;
  font-size: var(--fs-xs);
  transition: border-color 0.15s ease, color 0.15s ease, opacity 0.15s ease;
}
.wv-chipbar-arrow:hover:not(:disabled) { border-color: var(--brand); color: var(--brand); }
.wv-chipbar-arrow:disabled { opacity: 0.3; cursor: default; }
.wv-chipbar-arrow-badge {
  position: absolute;
  top: -0.35rem;
  right: -0.35rem;
  min-width: 1.05rem;
  height: 1.05rem;
  padding: 0 0.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 2px;
  background: var(--button);
  color: #fff;
  font-size: var(--fs-2xs);
  font-weight: 700;
  line-height: 1;
}
.wv-chipbar-arrow-badge[hidden] { display: none; }

.wv-chipbar-scroll-wrap { position: relative; flex: 1 1 auto; min-width: 0; }
.wv-chipbar-scroll {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  scroll-behavior: smooth;
  height: 100%;
}
.wv-chipbar-scroll::-webkit-scrollbar { display: none; }

.wv-chipbar-group { display: flex; align-items: center; gap: 0.45rem; flex: 0 0 auto; }
.wv-chipbar-head {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--brand);
  opacity: 0.75;
  white-space: nowrap;
}
.wv-chipbar-chips { display: flex; align-items: center; gap: 0.35rem; flex: 0 0 auto; }
.wv-chipbar-divider {
  flex: 0 0 auto;
  width: 1px;
  align-self: stretch;
  min-height: 1.6rem;
  margin: 0 0.15rem;
  background: #e2e2e2;
}
/* Right-edge fade — only painted when there's overflow to the right. */
.wv-chipbar-fade {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: 2.5rem;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(to right, rgba(255,255,255,0), #fff);
  transition: opacity 0.15s ease;
}
.wv-chipbar-scroll-wrap.has-overflow-right .wv-chipbar-fade { opacity: 1; }

/* Favourite card placeholder — used when a saved fav has no stored image
 * (e.g. room cards that don't carry one). Brand-tinted gradient with a
 * heart so the card still reads as a favourite at a glance. */
.wv-fav-card-placeholder {
  height: 140px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #fbede9 0%, #f6d9cd 100%);
  color: var(--brand);
  font-size: var(--fs-2xl);
}

/* Heart / favourites button overlay on cards. Airbnb-style — just the
 * outlined heart icon (no background button), with a soft drop-shadow halo
 * so it stays visible on both photos and white card surfaces. Clicks are
 * caught by the capture-phase delegated handler in chrome.js. */
.wv-fav-btn {
  position: absolute;
  top: 0.4rem;
  right: 0.4rem;
  z-index: 3;
  background: transparent;
  border: 0;
  padding: 0.2rem;
  cursor: pointer;
  font-size: var(--fs-md);
  line-height: 1;
  color: rgba(255, 255, 255, 0.95);
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.5));
  transition: transform 0.15s, color 0.15s, filter 0.15s;
}
.wv-fav-btn:hover { transform: scale(1.1); }
.wv-fav-btn.is-fav {
  color: var(--button);
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.25));
}
@media (prefers-reduced-motion: reduce) {
  .wv-fav-btn { transition: none; }
  .wv-fav-btn:hover { transform: none; }
}
/* Stay-kind toggle on the homepage filter card. Sits above the rest of the
 * filter form as a primary product decision (fixed vs flexible dates). */
.wv-stay-kind-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.wv-stay-kind-btn { font-size: var(--fs-sm); padding: 0.3rem 0.9rem; }
.wv-stay-kind-btn.btn-primary {
  background-color: var(--button);
  border-color: var(--button);
}

/* Compact chips for the thin bar. Sage outline by default; brand-green filled
 * when selected (Fusion). Squared. Used across every group (price/type/floor/
 * size/view/term/guarantor/allocation/features). */
.wv-feature-chip {
  font-size: var(--fs-xs);
  letter-spacing: 0.02em;
  padding: 0.2rem 0.6rem;
  line-height: 1.3;
  max-width: 240px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  background: #fff;
  border: 1px solid rgba(55, 84, 59, 0.35);
  border-radius: 2px;
  color: var(--brand-dark);
  font-weight: 600;
  transition: border-color 0.12s ease, box-shadow 0.12s ease, background-color 0.12s ease, color 0.12s ease;
}
.wv-feature-chip i { margin-right: 0.3rem; opacity: 0.8; }
.wv-feature-chip-uplift {
  font-size: var(--fs-2xs);
  opacity: 0.85;
  margin-left: 0.15rem;
  font-weight: 600;
}

.wv-feature-chip:hover { border-color: var(--brand); }

/* Selected: brand-green fill, white text. */
.wv-feature-chip.is-selected {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}
.wv-feature-chip.is-selected i { opacity: 0.95; }

/* Upsell dimension rows (Size / Floor / etc. on roomType + room cards) —
 * each option becomes a small pill. Included options show in green with a
 * check; options with an uplift price show in soft pink. */
.wv-upsell-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  margin: 0.25rem 0;
  font-size: var(--fs-xs);
}
.wv-upsell-label {
  color: #666;
  font-weight: 500;
  margin-right: 0.2rem;
  min-width: 3.5rem;
}
.wv-upsell-label i { color: var(--brand); margin-right: 0.25rem; }
.wv-upsell-option {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.55rem;
  border-radius: 1rem;
  background: #f3f3f3;
  color: #555;
  white-space: nowrap;
}
.wv-upsell-option.is-included {
  background: #e8f7ec;
  color: #1a7f37;
}
.wv-upsell-option.is-included::before {
  content: '✓';
  font-weight: 600;
  font-size: var(--fs-xs);
}
.wv-upsell-option.has-uplift {
  background: rgba(161, 77, 61, 0.10);
  color: var(--brand-dark);
}
.wv-upsell-uplift { font-weight: 600; }

/* Add-on cards (addons.html) — image-led card with checkbox in the corner.
 * The whole card is the label, so clicking anywhere toggles the addon. */
.addon-card {
  display: block;
  position: relative;
  background: white;
  border: 1px solid var(--line);
  border-radius: 0.9rem;
  overflow: hidden;
  cursor: pointer;
  height: 100%;
  /* Same resting glow + hover lift language as the other clickable cards —
   * soft pink drop shadow only, no hard ring on hover. */
  box-shadow: 0 6px 18px rgba(161, 77, 61, 0.10);
  transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
.addon-card:hover {
  box-shadow: 0 14px 32px rgba(161, 77, 61, 0.22);
  transform: translateY(-3px);
}
/* Selected state DOES need an edge to communicate "this is checked" — rust to match the CTA buttons. */
.addon-card:has(.addon-card-check:checked) {
  border-color: var(--button);
  box-shadow: 0 0 0 3px rgba(161, 77, 61, 0.35);
}
.addon-card-img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
}
.addon-card-body { padding: 0.85rem 1rem; }
.addon-card-check {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  width: 24px;
  height: 24px;
  z-index: 2;
  background-color: white;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}
/* Extras selection is an "add to order" action, so the tick uses the rust CTA colour
   (the global .form-check-input:checked is brand green) — consistent with the buttons. */
.addon-card-check:checked {
  background-color: var(--button);
  border-color: var(--button);
}
@media (prefers-reduced-motion: reduce) {
  .addon-card { transition: none; }
  .addon-card:hover { transform: none; }
}

/* "Your extras" (profile) — subscriptions and one-off orders as image-led cards,
   sharing the booking-card grid/glow/lift language. */
.wv-extra-card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 0.9rem;
  overflow: hidden;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
  transition: box-shadow 0.18s ease, transform 0.18s ease;
}
.wv-extra-card:hover {
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.14);
  transform: translateY(-2px);
}
.wv-extra-card--ended { opacity: 0.7; }

/* Media band — product photo over a tinted icon fallback; the type badge rides the corner. */
.wv-extra-card-media {
  position: relative;
  aspect-ratio: 16 / 9;
  display: grid;
  place-items: center;
  background: rgba(0, 0, 0, 0.05);
  overflow: hidden;
}
.wv-extra-card-media-ico { color: var(--brand); font-size: var(--fs-2xl); opacity: 0.45; }
.wv-extra-card-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.wv-extra-type-badge {
  position: absolute;
  top: 0.6rem;
  left: 0.6rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.22rem 0.55rem;
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
}
.wv-extra-type-badge--sub    { background: var(--brand-dark, #243a27); color: #fff; }
.wv-extra-type-badge--oneoff { background: var(--brand-dark, #243a27); color: #fff; }

.wv-extra-card-body { display: flex; flex-direction: column; flex: 1 1 auto; padding: 0.9rem 1.05rem 1rem; }
.wv-extra-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.5rem; }
.wv-extra-card-head .wv-status-pill { margin: 0; flex: 0 0 auto; }
.wv-extra-card-name { font-weight: 600; color: var(--ink); line-height: 1.25; }
.wv-extra-card-price { font-size: var(--fs-xl); font-weight: 700; color: var(--ink); line-height: 1; margin-top: 0.4rem; }
.wv-extra-card-price .cadence { font-size: var(--fs-sm); font-weight: 500; color: #888; margin-left: 0.15rem; }
.wv-extra-card-meta { color: #888; font-size: var(--fs-sm); margin-top: 0.35rem; }
.wv-extra-card-foot { margin-top: auto; padding-top: 0.9rem; }
.wv-extra-card-foot:empty { display: none; }
.wv-extras-orders-title { font-size: var(--fs-md); margin-top: 0; }
@media (prefers-reduced-motion: reduce) {
  .wv-extra-card { transition: none; }
  .wv-extra-card:hover { transform: none; }
}

/* Booking status ribbon — top-left of a booking card's image, same chip family as the
   catalog availability badge (.wv-avail-badge). Replaces the old per-section headers. */
.wv-booking-badge {
  position: absolute;
  top: 0.6rem;
  left: 0.6rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.28rem 0.65rem;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
}
.wv-booking-badge--draft     { background: var(--accent-warm, #ff7844); color: #1d1d1b; }
.wv-booking-badge--current   { background: var(--brand, #37543b); color: #fff; }
.wv-booking-badge--future    { background: #0a66c2; color: #fff; }
.wv-booking-badge--past      { background: #8a8a8a; color: #fff; }
.wv-booking-badge--cancelled { background: #c8353f; color: #fff; }

/* Profile page — one consistent gap above every major section heading, so
   Your details / Your bookings / Your extras / interests read as an even rhythm. */
.wv-profile > .wv-interests-head,  /* "Your bookings" head */
.wv-profile > #extras-section,     /* "Your extras" */
.wv-profile #interests-card {      /* "Your interests" */
  margin-top: 3.5rem;
}
.wv-profile > #details-section { margin-top: 0; }
.wv-profile #extras-orders-wrap { margin-top: 2rem; }  /* sub-block of extras — deliberately tighter */
.wv-profile .wv-interests-head h2 { margin-top: 0; }      /* align with the EDIT button in the flex head */
.wv-profile .wv-interests-head .btn { margin-top: -3px; } /* nudge the section-head action up to sit level with the heading */

/* Empty-state card — soft dashed panel with an icon, one line of copy and the relevant CTA.
   Shared across "no bookings", "no extras" and "no interests". */
.wv-empty-card {
  border: 2px dashed var(--line);
  border-radius: 0.9rem;
  padding: 2rem 1.5rem;
  text-align: center;
  color: #888;
  background: rgba(0, 0, 0, 0.015);
}
.wv-empty-card-ico { display: block; font-size: var(--fs-2xl); color: var(--brand); opacity: 0.5; margin-bottom: 0.6rem; }
.wv-empty-card-text { margin-bottom: 0.9rem; }

/* Hover affordance for clickable cards: soft pink halo + tiny lift. The halo
 * is a translucent ring (no hard border edge) so it reads as "highlighted"
 * without looking like the card grew an extra outline. Scoped to anchor cards
 * (wholesale-clickable) — div cards with internal CTAs keep their button hover. */
/* Cards that act as clickable units get the resting glow + hover lift.
 * Two flavours:
 *   - <a class="card">             — wholesale anchor card (city, building, popular)
 *   - <div class="card"> with .stretched-link inside — div card whose CTA
 *     button extends to cover the whole card (rooms, tenancy)
 * The :has() selector applies the same treatment to the second flavour. */
main a.card,
main .card:has(.stretched-link) {
  transition: box-shadow 0.18s ease, transform 0.18s ease;
  /* Rest: neutral, low-key. Hover gets the pink brand tint. */
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  /* Airbnb-style rounded corners. overflow: hidden so the card-img-top
   * inherits the rounding cleanly. */
  border-radius: 0.9rem;
  overflow: hidden;
}
main a.card:hover,
main .card:has(.stretched-link):hover {
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.14);
  transform: translateY(-3px);
}
main a.card .card-img-top,
main .card .card-img-top { border-radius: 0; }
@media (prefers-reduced-motion: reduce) {
  main a.card,
  main .card:has(.stretched-link) { transition: none; }
  main a.card:hover,
  main .card:has(.stretched-link):hover { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  main a.card { transition: none; }
  main a.card:hover { transform: none; }
}

/* "Also available" cards (excluded by filter) — visually softer */
.wv-also-section { margin-top: 2rem; }
.wv-also-section h2 { font-size: var(--fs-md); color: #888; }
.wv-also-section .card { opacity: 0.65; border-style: dashed; }
.wv-also-section .card:hover { opacity: 1; border-style: solid; }
/* The horizontal room-type cards are borderless by design — without this, the :hover rule above
   out-specifies their `border: none` and resurrects a `medium currentColor` (black) border. */
.wv-also-section .wv-card-h-col .card,
.wv-also-section .wv-card-h-col .card:hover { border: none; }
.wv-excluded-by {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin-bottom: 0.5rem;
}
.wv-excluded-by .wv-tag {
  background: #fbede9;
  color: #813c30;
  border-color: #e8c5b8;
  font-size: var(--fs-xs);
}

/* User icon in the top-right of the header (replaces sign-in/register text).
 * Sized to match the search trigger so the two icons sit as a balanced pair. */
.wv-user-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.8rem;
  height: 2.8rem;
  font-size: var(--fs-xl);
  color: #b3b3b3;
  text-decoration: none;
  line-height: 1;
  transition: color 0.15s, transform 0.15s;
}
.wv-user-icon:hover {
  color: var(--brand);
  text-decoration: none;
}
.wv-user-icon.wv-user-trigger {
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
}

/* Logged-in trigger: avatar (left) + "Hi {name}" (right), one clickable pill. */
.wv-user-trigger {
  display: inline-flex; align-items: center; gap: 0.55rem;
  background: transparent; border: 0; padding: 0.2rem 0.5rem; cursor: pointer;
  color: #fff; line-height: 1; border-radius: 999px; transition: background 0.15s ease;
}
.wv-user-trigger:hover { background: rgba(255, 255, 255, 0.10); }
.wv-user-avatar {
  width: 3rem; height: 3rem; border-radius: 50% !important; object-fit: cover;
  border: 1px solid rgba(255, 255, 255, 0.7); flex: 0 0 auto; display: block;
}
.wv-user-avatar-icon { font-size: var(--fs-xl); color: #fff; }
.wv-user-trigger .wv-greeting { margin: 0; color: #fff; white-space: nowrap; font-size: var(--fs-base); }

/* Logged-out: "Sign in" text link + "Register" rust button. */
.wv-auth-links { display: inline-flex; align-items: center; gap: 0.3rem; }
.wv-auth-link {
  color: #fff; text-decoration: none; font-size: var(--fs-base); font-weight: 600;
  padding: 0.45rem 0.85rem; border-radius: 999px; white-space: nowrap; transition: background 0.15s ease;
}
.wv-auth-link.wv-auth-signin:hover { background: rgba(255, 255, 255, 0.12); color: #fff; text-decoration: none; }
.wv-auth-link.wv-auth-register { background: var(--button); text-transform: uppercase; letter-spacing: 0.02em; }
.wv-auth-link.wv-auth-register:hover { background: var(--button-dark); color: #fff; text-decoration: none; }

/* Auth PAGES (sign in / create account) — a centred white card on the page background. */
.wv-auth-main {
  max-width: 640px;
  min-height: calc(100vh - 6.5rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* Hold the auth card at 640px even mid-funnel — out-specifies `body.wv-has-summary main { max-width:1440px }`
   so the basket can sit in the right rail while the card stays its proper width, centred in the content area. */
body.wv-has-summary main.wv-auth-main { max-width: 640px; }
.wv-auth-card {
  background: #fff;
  border: 1px solid var(--line);
  padding: 1.75rem 1.75rem 2rem;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.10);
}
.wv-auth-title { margin: 0 0 1.25rem; }
.wv-auth-card .form-control { border: 1px solid var(--line); }
.wv-auth-card .form-control:focus { border-color: var(--button); box-shadow: 0 0 0 0.15rem color-mix(in srgb, var(--button) 22%, transparent); }
.wv-auth-card .form-label { font-weight: 600; font-size: var(--fs-sm); margin-bottom: 0.3rem; }
/* Underlined tab control for the sign-in methods. */
.wv-auth-tabs { border-bottom: 1px solid var(--line); gap: 0.25rem; }
.wv-auth-tabs .nav-link { color: var(--ink); border: 0; border-bottom: 2px solid transparent; padding: 0.5rem 0.9rem; background: transparent; font-weight: 600; }
.wv-auth-tabs .nav-link:hover { color: var(--button); }
.wv-auth-tabs .nav-link.active { color: var(--brand-dark); border-bottom-color: var(--button); background: transparent; }
.wv-auth-alt { color: #6c6c6c; text-decoration: none; }
.wv-auth-alt strong { color: var(--button); }
.wv-auth-alt:hover strong { color: var(--button-dark); }

/* User dropdown — sibling pattern to .wv-scenario-menu but anchored to the
 * right edge of the page chrome instead of the left. */
.wv-user-wrap { position: relative; display: inline-flex; }
.wv-user-menu {
  display: none;
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 0.4rem;
  /* Match the trigger (avatar + name) width above it. */
  min-width: 100%;
  list-style: none;
  padding: 0.4rem 0;
  background: white;
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.10);
  z-index: 2000;
}
.wv-user-menu.show { display: block; }
.wv-user-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 0.55rem 1rem;
  cursor: pointer;
  font-family: inherit;
  font-size: var(--fs-sm);
  color: var(--ink);
  text-decoration: none;
}
.wv-user-item:hover, .wv-user-item:focus {
  background: rgba(161, 77, 61, 0.08);
  color: var(--brand-dark);
}
.wv-user-item i { color: var(--brand); width: 1rem; }
/* Sign-out lives in the (white) dropdown, so override the header-bar white text. */
#wv-chrome .wv-user-menu .wv-signout { color: var(--ink); }

/* Collapsible search: one icon-button (the trigger = submit). Default state
 * is just a grey magnifying glass. Hover or focus expands the input to the
 * LEFT of the trigger; the trigger itself morphs from a round grey icon into
 * a pink pill-end attached to the input — single search icon at all times. */
.wv-search-form {
  position: relative;
  display: flex;
  align-items: center;
  flex-direction: row;
}
.wv-search-input {
  /* Absolutely centred in the bar. Width scales with the viewport but always leaves ~530px clearance
     each side (1060 = 2×530), so the centred input never reaches the brand or the account block; capped
     at 620 on wide screens. Hidden below 1180 (see media query) where it'd be too small to be useful. */
  width: min(620px, calc(100vw - 1060px));
  height: 2.6rem;
  box-sizing: border-box;
  flex: 0 1 auto;
  min-width: 0;
  border: 1px solid var(--line);
  border-right: none;
  border-radius: 1.4rem 0 0 1.4rem;
  padding: 0 0.9rem;
  font-size: var(--fs-base);
  line-height: 1.4;
  opacity: 1;
  pointer-events: auto;
  background: white;
  transition:
    width 0.28s cubic-bezier(0.2, 0.8, 0.2, 1),
    padding 0.2s ease,
    opacity 0.2s ease;
}
.wv-search-form:hover .wv-search-input,
.wv-search-form:focus-within .wv-search-input {
  width: min(620px, calc(100vw - 1060px));
  padding: 0 0.9rem;
  opacity: 1;
  pointer-events: auto;
}
.wv-search-input:focus {
  outline: 0;
  border-color: var(--brand);
  box-shadow: none;
}
.wv-search-trigger {
  /* Always the rust pill-end of the (always-expanded) search bar, sized to the input height. */
  background: var(--button);
  border: 0;
  padding: 0;
  width: 2.8rem;
  height: 2.6rem;
  border-radius: 0 1.4rem 1.4rem 0;
  color: #fff;
  font-size: var(--fs-lg);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  line-height: 1;
  position: relative;
  top: 0;
}
/* fa-magnifying-glass also has its lens off-centre to the upper-left in
 * its glyph box; nudge the icon 1px left for optical centring within the
 * trigger button. */
.wv-search-trigger > i {
  /* Standalone rust button now — a normal-sized glyph, not the oversized one that matched the old icon. */
  transform: none;
  transform-origin: center;
  position: relative;
  top: 0;
  left: 0;
  transition:
    background 0.2s ease,
    color 0.2s ease,
    border-radius 0.2s ease,
    height 0.2s ease,
    width 0.2s ease;
}
.wv-search-trigger:hover { background: var(--button-dark); color: #fff; }
/* When form is open: trigger morphs into the pink pill-end of the search bar. */
/* (Removed the collapse-era hover/focus trigger rule — it changed the pill width 2.8rem→3rem on hover.
   The always-expanded .wv-search-trigger default already styles the rust pill + darken-on-hover.) */

/* Suggestions popover drops below the expanded form on focus. Stretched to
 * match the form's exact width (input + trigger pill) by anchoring left+right
 * to 0 inside the position:relative form parent — keeps the popover edges
 * flush with the search bar above it. */
.wv-search-suggestions {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  max-width: 90vw;
  background: white;
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.10);
  padding: 0.4rem 0;
  /* Above the basket/package-summary (z-index 1030), below Bootstrap modals (1050). */
  z-index: 1035;
}
.wv-search-suggestions[hidden] { display: none; }

/* vanillajs-datepicker — the portal's single date picker (DOB + summer-let), themed to the operator:
   our font, brand-green header/weekdays/Today, rust selection + range. */
.datepicker-picker { font-family: inherit; box-shadow: 0 10px 28px rgba(0,0,0,0.16); }
/* Match the calendar dropdown to the trigger input's width (the dropdown width itself is synced to the
   input on 'show'; here the picker + its grids stretch to fill that width instead of a fixed cell size). */
.datepicker-picker { width: 100%; box-sizing: border-box; }
.datepicker-picker .datepicker-main { padding: 0; }
.datepicker-picker .datepicker-grid { width: 100%; grid-template-columns: repeat(7, 1fr); }
.datepicker-picker .days-of-week { display: grid; grid-template-columns: repeat(7, 1fr); }
.datepicker-picker .datepicker-cell,
.datepicker-picker .dow { width: auto; }
.datepicker-picker .datepicker-controls .button { font-family: inherit; color: var(--brand); }
.datepicker-controls .view-switch { font-weight: 700; color: var(--brand); }
.datepicker-view .dow { color: var(--brand); font-weight: 700; }
.datepicker-cell { color: var(--ink); }
.datepicker-cell.selected, .datepicker-cell.selected:hover,
.datepicker-cell.range-start, .datepicker-cell.range-end { background: var(--button); color: #fff; }
.datepicker-cell.range { background: color-mix(in srgb, var(--button) 16%, #fff); border-radius: 0; }
.datepicker-cell.today:not(.selected) { background: var(--brand); color: #fff; font-weight: 700; }
.datepicker-cell.focused:not(.selected) { background: color-mix(in srgb, var(--button) 18%, #fff); }
.datepicker-cell:not(.selected):not(.disabled):hover { background: color-mix(in srgb, var(--button) 12%, #fff); }
.datepicker-picker .datepicker-header .button:hover,
.datepicker-footer .button:hover { background: color-mix(in srgb, var(--button) 14%, #fff); }
/* TODAY button — muted text, centred, no border/background. */
.datepicker-footer .datepicker-controls { justify-content: center; }
.datepicker-footer .button.today-button {
  flex: 0 1 auto; width: auto;
  background: transparent; border: 0; box-shadow: none;
  color: #6c757d; font-weight: 600;
}
.datepicker-footer .button.today-button:hover { background: transparent; color: var(--brand); }
.wv-search-suggestions-hint {
  margin: 0;
  padding: 0.35rem 1rem 0.5rem;
  font-size: var(--fs-xs);
  color: #999;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.wv-search-suggestion {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 0.55rem 1rem;
  cursor: pointer;
  font-size: var(--fs-sm);
  color: var(--ink);
}
.wv-search-suggestion i { color: #aaa; font-size: var(--fs-xs); }
.wv-search-suggestion:hover,
.wv-search-suggestion:focus { background: rgba(161, 77, 61, 0.08); color: var(--brand-dark); }
.wv-search-suggestion:hover i,
.wv-search-suggestion:focus i { color: var(--brand); }

.wv-chrome-inner { gap: 1rem; }
.wv-chrome-right { display: inline-flex; align-items: center; gap: 0.6rem; }
@media (max-width: 1180px) {
  /* The centred search scales with the viewport (see input width); below ~1180 it'd be too small to be
     useful, so hide it rather than show a sliver. */
  .wv-search-form { display: none; }
}

/* Price delta badge on Also-available cards */
.wv-also-section .badge { font-size: var(--fs-xs); }

/* ============================================================
 * A.7.4 — social-proof signals + trust strip
 * ============================================================ */

.wv-signals-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.6rem;
}

.wv-signal {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.65rem;
  border-radius: 1rem;
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: 1;
}

.wv-signal-live      { background: #e7f3fe; color: #0a66c2; }
.wv-signal-velocity  { background: #e8f7ec; color: #1a7f37; }
.wv-signal-scarcity  { background: #fff4d6; color: #9a6700; }
.wv-signal-hot       { background: #fdecdd; color: #b3401e; }
.wv-signal-hot i     { color: #e8590c; }

.wv-coming-soon {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0.6rem;
  border-radius: 1rem;
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1;
  background: #eef0f3;
  color: #44505f;
}
.wv-card-coming-soon { opacity: 0.72; cursor: default; }
.wv-card-coming-soon:hover { box-shadow: none; transform: none; }

.wv-card-media { position: relative; }

.wv-coming-soon-opening {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--brand, #37543b);
  font-weight: 600;
  margin: 0.25rem 0 0.5rem;
}
.wv-register-interest { padding: 2rem 1rem; }

/* Chip geometry shared with .wv-avail-badge so image-corner badges read as one family. */
.wv-coming-soon-banner {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.28rem 0.65rem;
  background: var(--brand, #37543b);
  color: #fff;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
}

@keyframes wvPulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}

@media (prefers-reduced-motion: reduce) {
  .wv-signal-live i, .wv-signal-velocity i, .wv-signal-hot i { animation: none; }
}

.wv-reviews-inline {
  font-size: var(--fs-sm);
  color: #9a6700;
  margin-left: 0.4rem;
  font-weight: 500;
}

.wv-trust-strip {
  background: white;
  border-top: 1px solid var(--line);
  color: #6b6b6b;
  padding: 0.9rem 1rem;
  margin-top: 2rem;
  font-size: var(--fs-sm);
}

.wv-trust-strip-inner {
  max-width: 1140px;
  margin: 0 auto;
  padding: 0 0.5rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.wv-trust-strip-copy {
  color: #888;
  font-size: var(--fs-sm);
}

.wv-trust-strip-badges {
  display: inline-flex;
  gap: 1.5rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.wv-trust-strip-badges span {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.wv-trust-strip i { color: #9b9b9b; }

/* ============================================================
 * A.7.5 — recent activity toast (bottom-right, WookiVerse-themed)
 * ============================================================ */

.wv-recent-toast {
  position: fixed;
  bottom: 1rem;
  /* Bottom-LEFT (social-proof convention) so it doesn't collide with the chat FAB / basket on the right. */
  left: 1.5rem;
  background: white;
  border: 1px solid var(--line);
  border-radius: 0.75rem;
  box-shadow: 0 10px 28px rgba(161, 77, 61, 0.18);
  padding: 0.85rem 1rem;
  font-size: var(--fs-sm);
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 0.85rem;
  width: 380px;
  max-width: calc(100vw - 3rem);
  z-index: 9999;
  /* Default: hidden off-screen to the right + transparent. The .is-visible
   * class slides it in. Removing the class slides it back out. */
  opacity: 0;
  transform: translateX(-120%);
  transition:
    opacity 0.35s ease-out,
    transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
  pointer-events: none;
}

.wv-recent-toast.is-visible {
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
}

.wv-recent-toast-icon {
  /* Fallback when the event has no image. */
  flex: 0 0 auto;
  width: 64px;
  height: 64px;
  border-radius: 0.5rem;
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-dark) 100%);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-lg);
  box-shadow: 0 2px 10px rgba(161, 77, 61, 0.25);
}

.wv-recent-toast-image {
  flex: 0 0 auto;
  width: 64px;
  height: 64px;
  border-radius: 0.5rem;
  object-fit: cover;
  border: 2px solid var(--brand);
  box-shadow: 0 2px 10px rgba(161, 77, 61, 0.25);
  display: block;
}

.wv-recent-toast-body {
  flex: 1 1 auto;
  line-height: 1.35;
  min-width: 0;
}
.wv-recent-toast-body strong { color: var(--brand-dark); font-weight: 600; }
.wv-recent-toast-time { color: #999; font-size: var(--fs-xs); display: block; margin-top: 0.15rem; }

.wv-recent-toast-close {
  position: absolute;
  top: -0.5rem;
  right: -0.5rem;
  background: var(--button);
  border: 2px solid white;
  border-radius: 50%;
  width: 24px;
  height: 24px;
  font-size: var(--fs-base);
  font-weight: 700;
  line-height: 1;
  color: white;
  cursor: pointer;
  /* `&times;` glyph sits low in its box; padding-bottom nudges it up to
   * visual centre. */
  padding: 0 0 3px 0;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 6px rgba(0,0,0,0.18);
  transition: background 0.15s, transform 0.15s;
}
.wv-recent-toast-close:hover { background: var(--button-dark, #883f31); transform: scale(1.08); }

@media (prefers-reduced-motion: reduce) {
  .wv-recent-toast { transition: opacity 0.2s linear; }
  .wv-recent-toast,
  .wv-recent-toast.is-visible { transform: none; }
  .wv-recent-toast-close { transition: none; }
}

/* Error toast — same slide-in pattern as the activity toast but with a red
 * accent and an exclamation-mark icon. Stacked above the activity toast
 * when both are visible (chrome.js handles the bottom positioning). */
.wv-error-toast {
  position: fixed;
  bottom: 1rem;
  right: 1.5rem;
  background: white;
  border: 1px solid #f3c1c1;
  border-left: 4px solid #d83f3f;
  border-radius: 0.6rem;
  box-shadow: 0 10px 28px rgba(216, 63, 63, 0.18);
  padding: 0.75rem 0.95rem;
  font-size: var(--fs-sm);
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 380px;
  max-width: calc(100vw - 3rem);
  z-index: 10000;
  opacity: 0;
  transform: translateX(120%);
  transition:
    opacity 0.3s ease-out,
    transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
  pointer-events: none;
}
.wv-error-toast.is-visible {
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
}
.wv-error-toast-icon {
  flex: 0 0 auto;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: #fdecec;
  color: #d83f3f;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-base);
}
.wv-error-toast-body { flex: 1 1 auto; line-height: 1.35; }
.wv-error-toast-close {
  background: transparent;
  border: 0;
  font-size: var(--fs-md);
  font-weight: 700;
  line-height: 1;
  color: #999;
  cursor: pointer;
  padding: 0 0.3rem;
}
.wv-error-toast-close:hover { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
  .wv-error-toast { transition: opacity 0.2s linear; }
  .wv-error-toast,
  .wv-error-toast.is-visible { transform: none; }
}

/* Don't crowd the trust strip — chrome.js's scroll handler bumps `bottom`
 * dynamically when the footer enters the viewport. On load, the toast sits
 * at the default 1rem from the bottom edge. */

/* Horizontal room-type cards on /building.html. Larger image, no border or
   shadow, generous padding — closer to fusionstudents.co.uk's room cards. */
.wv-card-h-col { margin-bottom: 1.5rem; }
.wv-card-h-col .card {
  flex-direction: row;
  overflow: hidden;
  background: #fff;
  border: none;
  box-shadow: none;
}
.wv-card-h-col .card-img-top {
  width: 45%;
  aspect-ratio: 16 / 9;
  height: auto;
  flex-shrink: 0;
  align-self: center;
  object-fit: cover;
}
/* The availability badge wraps the image in .wv-card-media, which becomes the flex child —
   the wrapper takes the 45% column and stretches to the card's full height (a tall body, e.g.
   an open waitlist form, zooms the image to fill rather than leaving gaps). The ::before keeps
   a 16:9 floor so short bodies still get a decent image. */
.wv-card-h-col .wv-card-media {
  width: 45%;
  flex-shrink: 0;
  align-self: stretch;
  position: relative;
}
.wv-card-h-col .wv-card-media::before { content: ''; display: block; padding-top: 56.25%; }
.wv-card-h-col .wv-card-media .card-img-top {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Clicking an anchor card leaves Chrome's default black focus ring on it — suppress for mouse,
   keep a brand ring for keyboard users. */
main a.card:focus { outline: none; }
main a.card:focus-visible { outline: 2px solid var(--brand, #37543b); outline-offset: 2px; }
.wv-card-h-col .card-body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 2rem 2.5rem;
}
.wv-card-h-col .card-title {
  font-size: var(--fs-xl);
  margin-bottom: 0.9rem;
}
.wv-card-h-col .card-text { font-size: var(--fs-base); line-height: 1.55; }
@media (max-width: 768px) {
  .wv-card-h-col .card { flex-direction: column; }
  .wv-card-h-col .card-img-top { width: 100%; aspect-ratio: 16 / 9; height: auto; min-height: 0; }
  .wv-card-h-col .wv-card-media { width: 100%; }
  .wv-card-h-col .card-body { padding: 1.25rem 1.5rem; }
  .wv-card-h-col .card-title { font-size: var(--fs-lg); }
}

/* ============================================================
 * Bookable mode badges + flip card (rooms.html)
 * ------------------------------------------------------------
 * Fusion theme: badges use brand greens / terracottas instead of
 * the default's pink/blue. Flip rotates on the X axis (horizontal,
 * top-over-bottom) rather than Y, as a brand-differentiation move
 * vs the default operator's vertical-axis flip.
 * ============================================================ */
.wv-mode-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.25em 0.65em;
  border-radius: 999px;
  font-size: var(--fs-xs);
  font-weight: 600;
  white-space: nowrap;
  flex-shrink: 0;
}
.wv-mode-badge.wv-mode-couple {
  background: rgba(161, 77, 61, 0.12);   /* --button (terracotta) tint */
  color: var(--button-dark, #813c30);
  border: 1px solid rgba(161, 77, 61, 0.25);
}
.wv-mode-badge.wv-mode-group {
  background: rgba(55, 84, 59, 0.12);     /* --brand (green) tint */
  color: var(--brand-dark, #243a27);
  border: 1px solid rgba(55, 84, 59, 0.25);
}

/* Spare-beds: bed-strip occupancy badge on the flat card. Filled = taken, outline = free. */
.wv-bed-strip { display: flex; align-items: center; gap: 0.25rem; flex-wrap: wrap; }
/* Little "room" tiles (wider than tall, like a bed) — always filled so free rooms never read as empty/broken
   boxes. Free = brand green (the thing we're advertising), taken = muted grey. */
.wv-bed {
  width: 0.85rem; height: 0.55rem; border-radius: 3px;
  background: #c8ccc3; flex: 0 0 auto;
}
.wv-bed.free { background: var(--brand, #37543b); }
.wv-bed.taken { background: #c8ccc3; }
.wv-bed-lbl { margin-left: 0.35rem; font-size: var(--fs-xs); color: var(--brand-dark, #243a27); font-weight: 600; }
.wv-book-spare { padding: 0.15rem 0.7rem; }

/* Standard loader — the rotating Fusion "+", centred in its container (search uses the button form). */
/* Fills the content area below the header so the + is centred on screen, not stranded near the top. */
.wv-spinner-panel { display: flex; align-items: center; justify-content: center; min-height: calc(100vh - 220px); padding: 2rem 1rem; }
.wv-spinner-panel .fa-plus { font-size: var(--fs-3xl); color: var(--button, #a14d3d); }

/* "How to sign" intro card — also rendered on the contract page as an instant placeholder while the signing
   frame loads (the frame, sign.html, carries its own copy of these rules for its embedded use). */
.wv-sigcard { border: 1px solid var(--line, #d8d5cc); border-radius: 12px; background: var(--paper, #fff); padding: 16px; margin: 0; }
.wv-sigcard-title { font-size: var(--fs-sm); font-weight: 700; margin: 0; }
.wv-sign-intro-card { margin: 6px 0 18px; }
.wv-sign-steps { margin: 0; padding-left: 20px; font-size: var(--fs-xs); color: var(--ink, #2b2b2b); line-height: 1.6; }
.wv-sign-steps li { margin-bottom: 4px; }
.wv-sign-steps li:last-child { margin-bottom: 0; }
.wv-signaction-text { font-size: var(--fs-xs); color: var(--muted, #6b6b66); line-height: 1.5; margin: 0 0 12px; }

/* "Push up" slide — Fusion variant. Instead of a 3D flip, the front slides
 * up out of view while the back slides up from below into view. Both
 * faces stack in the same grid cell (so the card auto-sizes to the
 * tallest face and the grid isn't disturbed); inner has overflow:hidden
 * so the off-screen back is clipped at rest, and the face transitions
 * use translateY rather than rotate. */
.card.wv-flip-card {
  background: transparent;
  border: 0;
  box-shadow: none;
  transition: transform 0.18s ease;
  perspective: 1400px;
}
main .wv-flip-card:hover {
  transform: translateY(-3px);
}
/* Grid keeps both faces stacked (auto-height = the taller face); preserve-3d + the faces'
   backface-visibility turn the toggle into a real card flip. overflow:hidden lives on the FACES,
   not the inner (it would force the inner to flatten and kill the 3D). */
.wv-flip-inner {
  display: grid;
  grid-template-areas: "face";
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 0.9rem;
}
.wv-flip-face {
  grid-area: face;
  background: var(--bs-body-bg, var(--paper, #fff));
  border: 1px solid var(--bs-border-color, var(--line, #d6d3c9));
  border-radius: 0.9rem;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  transition: box-shadow 0.18s ease;
}
main .wv-flip-card:hover .wv-flip-face {
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.14);
}
/* Resting: front faces the viewer, back is pre-rotated away. Flipped: the inner rotates 180°. */
.wv-flip-front { transform: rotateY(0deg); }
.wv-flip-back  { transform: rotateY(180deg); }
.wv-flip-card.is-flipped .wv-flip-inner { transform: rotateY(180deg); }

/* "Your group" panel on profile.html — surfaces the master booking's
 * invite slots with claim status + copy-link affordance for pending
 * invites. Uses Fusion's brand green for the claimed icon to match
 * the rest of the operator's palette. */
.wv-group-panel {
  border-top: 1px solid var(--bs-border-color, var(--line, #d6d3c9));
  padding-top: 0.75rem;
  margin-top: 0.75rem;
  margin-bottom: 0.75rem;
  position: relative;
  z-index: 2;
}
.wv-group-list {
  list-style: none;
  padding-left: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.wv-group-row {
  display: grid;
  grid-template-columns: 24px 1fr auto auto;
  gap: 0.6rem;
  align-items: center;
  padding: 0.4rem 0.5rem;
  border-radius: 0.4rem;
  background: rgba(0, 0, 0, 0.02);
  font-size: var(--fs-sm);
}
.wv-group-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-size: var(--fs-sm);
}
.wv-group-icon-claimed { color: var(--brand, #37543b); }
.wv-group-icon-pending { color: var(--button, #a14d3d); }
.wv-group-name { font-weight: 600; }
.wv-group-bedroom { color: var(--muted, #6c757d); font-size: var(--fs-sm); }
.wv-group-status-text { white-space: nowrap; }
.wv-copy-link { font-size: var(--fs-xs); padding: 0.2rem 0.55rem; }

/* Payment-model selector on invite.html — Fusion brand-themed checked
 * state (green) matching the rest of the operator's palette rather than
 * the default's blue. */
.wv-payment-options {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.wv-payment-option {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--bs-border-color, var(--line, #d6d3c9));
  border-radius: 0.5rem;
  cursor: pointer;
  transition: background 150ms ease, border-color 150ms ease;
}
.wv-payment-option:hover {
  background: rgba(55, 84, 59, 0.04);
}
.wv-payment-option > input[type="radio"] {
  margin-top: 0.3rem;
  flex-shrink: 0;
}
.wv-payment-option:has(input[type="radio"]:checked) {
  background: rgba(55, 84, 59, 0.08);   /* --brand (green) tint */
  border-color: rgba(55, 84, 59, 0.4);
}

/* Bedroom-list row layout (back face). */
.wv-flat-bedroom-list {
  list-style: none;
  padding-left: 0;
  font-size: var(--fs-sm);
}
.wv-flat-bedroom-list > li {
  padding: 0.4rem 0;
  border-top: 1px solid var(--bs-border-color, var(--line, #d6d3c9));
}
.wv-flat-bedroom-list > li:first-child {
  border-top: none;
  padding-top: 0;
}
.wv-flat-bedroom-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.wv-flat-bedroom-tags {
  display: flex;
  gap: 0.25rem;
  flex-wrap: wrap;
}
.wv-tag-mini {
  font-size: var(--fs-2xs);
  padding: 0.05em 0.4em;
  margin-left: 0.25em;
}

@media (prefers-reduced-motion: reduce) {
  .card.wv-flip-card { transition: none; }
  main .wv-flip-card:hover { transform: none; }
  .wv-flip-face { transition: none; }
  .wv-flip-inner { transition: none; }
}

/* ============================================================
 * Search results page (/search)
 * ------------------------------------------------------------
 * Rendered by /shared/search-results.js: answer line, summary
 * strip, geography groups, building cards with matched chips,
 * near misses (amber), unmatched honesty line.
 * ============================================================ */
.wv-results-answer {
  display: none;   /* search-results summary banner hidden per operator preference */
  background: #e9efe6;
  border: 1px solid #c8d5c2;
  border-left: 4px solid var(--brand);
  color: var(--brand-dark);
  padding: 0.8rem 1rem;
  margin-bottom: 1.25rem;
  font-size: var(--fs-base);
  align-items: center;
  gap: 0.6rem;
}
.wv-results-answer i { color: var(--brand); }

.wv-strip { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
.wv-strip-tile {
  flex: 1 1 140px;
  background: var(--paper);
  border: 1px solid var(--line);
  padding: 0.7rem 1rem;
  text-align: center;
}
.wv-strip-value { display: block; font-size: var(--fs-lg); font-weight: 700; color: var(--brand); }
.wv-strip-label {
  display: block;
  font-size: var(--fs-xs);
  color: #6c6c6c;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.wv-result-group-label {
  font-size: var(--fs-base);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand);
  margin: 1.75rem 0 0.75rem;
}

.wv-result-group {
  display: flex;
  flex-direction: column;
  margin-bottom: 1rem;
}

.wv-result-card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  margin-bottom: 1rem;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
/* Header (media + title/chips) is the building link; the offer subcards below
 * are their own links, so the head is a row inside the column card shell. */
/* Full-width property banner: image fills the head, title/meta/chips overlaid bottom-left. */
.wv-result-card-head {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 220px;
  text-decoration: none;
  color: #fff;
  overflow: hidden;
}
a.wv-result-card-head { transition: box-shadow 0.18s ease; }
a.wv-result-card-head:hover {
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
  color: #fff;
}
@media (prefers-reduced-motion: reduce) {
  a.wv-result-card-head { transition: none; }
}
.wv-result-card-media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.wv-result-card-media-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
  color: var(--line);
  font-size: var(--fs-2xl);
}
.wv-result-card-head::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(0deg, rgba(0,0,0,0.66) 0%, rgba(0,0,0,0.22) 55%, rgba(0,0,0,0) 100%);
  pointer-events: none;
}
.wv-result-card-body { position: relative; z-index: 2; width: 100%; min-width: 0; padding: 1rem 1.1rem; }
.wv-result-card-title { font-size: var(--fs-lg); margin-bottom: 0.15rem; color: #fff; }
.wv-result-card-meta { color: rgba(255,255,255,0.85); font-size: var(--fs-sm); margin-bottom: 0.45rem; }

.wv-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.5rem; }
.wv-chip {
  background: #e6ece4;
  color: var(--brand-dark);
  font-size: var(--fs-xs);
  font-weight: 600;
  padding: 0.18rem 0.6rem;
  white-space: nowrap;
}
.wv-chip-miss { background: #f7ecd8; color: #8a6116; }

/* The matched-room criteria chips ("South-facing", "Balcony") render in the card
 * header below the building chips (reusing .wv-chips). Slight top spacing to sit
 * a touch apart from the building chips above. */
.wv-rooms-criteria.wv-chips { margin-top: 0.1rem; }

/* The matched individual rooms now sit INSIDE each room-type subcard, as a small
 * clickable chip row under the price. .wv-offer-subcard wraps the tile <a> and the
 * rooms row (sibling, so the room chips aren't nested inside the tile's anchor). */
.wv-offer-subcard {
  position: relative;
  display: flex;
  flex-direction: row;
  background: var(--paper);
  border: 1px solid var(--line);
  overflow: hidden;
}
.wv-offer-subcard.is-link { cursor: pointer; transition: box-shadow 0.18s ease, transform 0.18s ease; }
.wv-offer-subcard.is-link:hover { box-shadow: 0 10px 22px rgba(0, 0, 0, 0.14); transform: translateY(-2px); border-color: var(--button); }
@media (prefers-reduced-motion: reduce) {
  .wv-offer-subcard.is-link { transition: none; }
  .wv-offer-subcard.is-link:hover { transform: none; }
}

/* Booking cards (profile "Your bookings") lift on hover like the main-page room/offer cards. */
.wv-booking-card { transition: box-shadow 0.18s ease, transform 0.18s ease; }
.wv-booking-card:hover { box-shadow: 0 10px 22px rgba(0, 0, 0, 0.14); transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) {
  .wv-booking-card { transition: none; }
  .wv-booking-card:hover { transform: none; }
}
.wv-rooms-criteria {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
}
.wv-rooms-count { font-weight: 700; }
/* Matched-room chip row under a subcard's price: one clipped nowrap line with a
 * right-aligned "+N more". Side padding aligns with the tile body above. */
.wv-rooms-names {
  font-size: var(--fs-xs);
  display: flex;
  align-items: center;
  gap: 0.35rem;
  min-width: 0;
  overflow: hidden;
  padding: 0.4rem 0 0;
}
.wv-rooms-names-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.35rem;
  min-width: 0;
  overflow: hidden;
}
/* Each room number is its own link; the inner span carries the chip look. Hover
 * picks up the operator's terracotta accent to read as clickable. */
.wv-room-link { flex: 0 0 auto; text-decoration: none; position: relative; z-index: 2; }
.wv-room-name {
  display: inline-block;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  background: #fff;
  border: 1px solid var(--line);
  padding: 0 0.35rem;
  white-space: nowrap;
  color: var(--ink);
}
a.wv-room-link:hover .wv-room-name { border-color: var(--button); color: var(--brand-dark); }
.wv-rooms-more {
  flex: 0 0 auto;
  margin-left: auto;
  color: #6c6c6c;
  white-space: nowrap;
}

.wv-offer-tiles {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.6rem;
  border-top: 1px solid var(--line);
  margin: 0 1rem;
  padding: 0.6rem 0;
}
@media (max-width: 560px) {
  .wv-offer-tiles { grid-template-columns: 1fr; }
}
.wv-offer-tile {
  display: flex;
  flex-direction: row;
  background: var(--paper);
  border: 1px solid var(--line);
  overflow: hidden;
  text-decoration: none;
  color: var(--ink);
}
/* Subcards that link to a type page get the clickable affordance — terracotta
 * accent on hover to match the operator's button language. */
a.wv-offer-tile { cursor: pointer; transition: box-shadow 0.18s ease, transform 0.18s ease; }
a.wv-offer-tile:hover {
  box-shadow: 0 10px 22px rgba(0, 0, 0, 0.14);
  transform: translateY(-2px);
  border-color: var(--button);
  color: var(--ink);
}
@media (prefers-reduced-motion: reduce) {
  a.wv-offer-tile { transition: none; }
  a.wv-offer-tile:hover { transform: none; }
}
.wv-offer-tile-img {
  /* Keep a 4:3 thumbnail: fills the card height, width follows the ratio (no tall stretch). */
  flex: 0 0 auto;
  align-self: stretch;
  aspect-ratio: 4 / 3;
  width: auto;
  max-width: 42%;
  background-size: cover;
  background-position: center;
}
.wv-offer-tile-img-empty {
  background: color-mix(in srgb, var(--brand) 10%, var(--paper));
}
.wv-offer-tile-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.1rem;
  padding: 0.5rem 0.75rem;
}
.wv-offer-tile-type { font-weight: 600; font-size: var(--fs-sm); color: var(--brand-dark); }
.wv-offer-tile-term { font-size: var(--fs-xs); color: #6c6c6c; }
.wv-offer-tile-price {
  font-size: var(--fs-base);
  font-weight: 700;
  color: var(--brand);
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.wv-instalment-badge {
  flex: 0 0 auto;
  font-size: var(--fs-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background: #e6ece4;
  color: var(--brand-dark);
  padding: 0.12rem 0.5rem;
}

.wv-near-miss-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 2rem 0 0.75rem;
  color: #8a6116;
  font-weight: 700;
  text-transform: uppercase;
  font-size: var(--fs-sm);
  letter-spacing: 0.08em;
}
.wv-near-miss-divider::before,
.wv-near-miss-divider::after { content: ''; flex: 1; border-top: 1px solid #ecd9ae; }

.wv-results-unmatched { color: #6c6c6c; font-style: italic; font-size: var(--fs-sm); margin-top: 1rem; }
.wv-results-notice { color: #6c6c6c; font-style: italic; font-size: var(--fs-sm); margin: 0 0 1.25rem; }
.wv-results-answer + .wv-results-notice { margin-top: -0.75rem; }
.wv-result-card > .wv-results-notice { margin: 0 1rem 0.8rem; }
.wv-results-empty { color: #6c6c6c; text-align: center; font-size: var(--fs-md); margin: 3rem 0; }

@media (max-width: 600px) {
  .wv-result-card-head { min-height: 180px; }
}

/* --- Property-header locale (address + map + what's nearby) -------------------
   Fusion theme: square corners (the global border-radius:0 !important catch-all
   applies), sage borders, green headings. The marker circles are the deliberate
   exception — overridden back to round below. */
.wv-property-locale-section { margin-top: 2.5rem; }
/* Stacked: full-width map on top, chip filter bar, then the multi-column scrollable list. */
.wv-property-locale { margin: 0 0 2rem; display: flex; flex-direction: column; gap: 1.1rem; }
.wv-locale-map {
  width: 100%; min-height: 520px; overflow: hidden;
  border: 1px solid var(--line); background: var(--paper);
}
/* Chip filter bar — sits between map and list. */
.wv-locale-chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.wv-locale-chip {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: var(--fs-xs); letter-spacing: 0.05em; line-height: 1.4;
  padding: 0.25rem 0.65rem; cursor: pointer;
  border: 1px solid #c9c9c9; background: #fff; color: #555;
  transition: background-color 0.12s, border-color 0.12s, color 0.12s, opacity 0.12s;
}
.wv-locale-chip:hover { border-color: var(--button); }
/* Active = solid brand fill; the icon switches to white so it stays legible on the fill. */
.wv-locale-chip.is-on {
  background: var(--button); border-color: var(--button); color: #fff;
  box-shadow: 0 1px 4px rgba(151, 79, 62, 0.25);
}
.wv-locale-chip.is-on i { color: #fff !important; }
/* Inactive = quiet grey outline (icon keeps its brand colour as the only hint of hue). */
.wv-locale-chip:not(.is-on) { opacity: 0.85; }
/* Inside the thin scrolling bar: chips keep their width (no shrink) and the bar relies on the
   locale section's column gap rather than its own bottom margin. */
.wv-locale-chipbar { margin-bottom: 0; }
.wv-locale-chipbar .wv-locale-chip { flex: 0 0 auto; }
/* List = full-width, multi-column, scroll-capped so a long list never dominates the page. */
.wv-locale-nearby {
  border: 1px solid var(--line);
  background: var(--paper); padding: 1.1rem 1.25rem;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 0.6rem 1.5rem; align-content: start;
  max-height: 520px; overflow-y: auto;
}
.wv-locale-nearby-head {
  font-size: var(--fs-md); margin: 0 0 0.75rem;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--brand);
}
.wv-locale-nearby-empty { font-size: var(--fs-base); }
/* Each category is now a grid item; the grid `gap` provides the spacing. */
.wv-locale-cat { min-width: 0; }
.wv-locale-cat-head {
  display: flex; align-items: center; gap: 0.5rem;
  font-size: var(--fs-sm); font-weight: 600; margin: 0 0 0.35rem; color: var(--brand);
  text-transform: uppercase; letter-spacing: 0.05em;
}
.wv-locale-poi-list { list-style: none; margin: 0; padding: 0; }
.wv-locale-poi {
  display: grid; grid-template-columns: minmax(0, 1fr) auto 1rem;
  align-items: baseline; column-gap: 0.5rem;
  padding: 0.2rem 0; font-size: var(--fs-sm);
}
/* Name truncates; the minutes then the mode icon sit in their own aligned columns. */
.wv-locale-poi-name {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.wv-locale-poi-mode { color: #6c6c6c; text-align: center; }
.wv-locale-poi-min { color: #6c6c6c; white-space: nowrap; text-align: right; min-width: 3.6em; }

/* ── Building reviews (cached Google aggregate + snippets) ───────────────────── */
.wv-reviews-section { margin-top: 2.5rem; }
.wv-reviews-summary { display: flex; align-items: baseline; gap: 0.6rem; margin-bottom: 1rem; flex-wrap: wrap; }
.wv-reviews-score { font-size: var(--fs-xl); font-weight: 800; color: var(--brand); }
.wv-reviews-stars { color: #f5a623; letter-spacing: 0.08em; }
.wv-reviews-count { color: #6c6c6c; font-size: var(--fs-base); }
.wv-reviews-grid { display: grid; gap: 1rem; transition: opacity 0.35s ease; }
.wv-reviews-grid.is-fading { opacity: 0; }
.wv-review { margin: 0; border: 1px solid var(--line); background: var(--paper); padding: 1rem; display: flex; flex-direction: column; }
.wv-review-stars { color: #f5a623; font-size: var(--fs-sm); margin-bottom: 0.4rem; }
.wv-review-text { margin: 0 0 0.6rem; font-size: var(--fs-sm); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; }
.wv-review-by { font-size: var(--fs-xs); color: #6c6c6c; margin-top: auto; }
.wv-reviews-attr { font-size: var(--fs-xs); margin-top: 0.8rem; }
/* Map marker hover popover: photo + name + rating/travel + Google summary. */
.wv-poi-popover.popover { max-width: 300px; }
.wv-poi-popover .popover-body { padding: 0; }
.wv-poi-pop { width: 280px; }
.wv-poi-pop-img { width: 100%; height: 130px; object-fit: cover; display: block; border-radius: 4px 4px 0 0; }
.wv-poi-pop-body { padding: 0.6rem 0.75rem; }
.wv-poi-pop-body strong { display: block; font-size: var(--fs-base); margin-bottom: 0.25rem; }
.wv-poi-pop-meta { display: flex; gap: 0.7rem; font-size: var(--fs-xs); color: #6c6c6c; margin-top: 0.5rem; }
.wv-poi-pop-rating { font-weight: 600; color: var(--brand-dark); }
.wv-poi-pop-rating i { color: #f5a623; }
.wv-poi-pop-sum { font-size: var(--fs-xs); line-height: 1.4; color: #333;
  display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden; }
/* FA-icon badge markers — round despite the square-everything catch-all. */
.wv-locale-marker {
  width: 28px; height: 28px; border-radius: 50% !important;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: var(--fs-xs); box-shadow: 0 1px 4px rgba(0,0,0,0.4);
  border: 2px solid #fff;
}
/* Building pin: visibly larger than the 28px POI badges and lifted above
   them so a coincident POI never sits on top of it. (initMap also adds it to
   the higher floatPane as a belt-and-braces layer guarantee.) */
.wv-locale-marker.is-building { width: 40px; height: 40px; font-size: var(--fs-md); z-index: 50; }
@media (max-width: 768px) {
  .wv-locale-map { min-height: 280px; }
  .wv-locale-nearby { grid-template-columns: 1fr; max-height: 420px; }
}

/* ── Room-detail header (tenancy page, above the picker) ─────────────────────
   Fusion theme: square corners (forced globally), sage line, brand-green spec
   icons. Gallery + info two-up on desktop, stacked on mobile. */
.wv-room-detail { margin: 0 0 2rem; }
.wv-rd-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}
.wv-rd-gallery { display: flex; flex-direction: column; gap: 0.6rem; }
/* Floorplan flip — the main picture flips to reveal the floorplan and back. */
.wv-rd-stage { aspect-ratio: 16 / 9; perspective: 1400px; }
.wv-rd-gallery > .wv-rd-carousel { aspect-ratio: 16 / 9; height: auto; }
.wv-rd-stage-inner { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: transform 0.55s ease; }
.wv-rd-stage.is-flipped .wv-rd-stage-inner { transform: rotateY(180deg); }
.wv-rd-face { position: absolute; inset: 0; overflow: hidden; border: 1px solid var(--line); backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.wv-rd-face .wv-rd-main, .wv-rd-face > img { width: 100%; height: 100%; aspect-ratio: auto; display: block; }
.wv-rd-face-front .wv-rd-main { object-fit: cover; }
.wv-rd-face-back { transform: rotateY(180deg); background: var(--paper); }
.wv-rd-face-back > img { object-fit: contain; }
.wv-rd-stage:not(.is-flipped) .wv-rd-face-back { pointer-events: none; }
.wv-rd-stage.is-flipped .wv-rd-face-front { pointer-events: none; }
.wv-rd-flipbtn { position: absolute; right: 10px; bottom: 10px; z-index: 2; display: inline-flex; align-items: center; background: var(--button); color: #fff; border: none; border-radius: 6px; padding: 7px 13px; font-size: var(--fs-sm); font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em; cursor: pointer; box-shadow: 0 1px 5px rgba(0,0,0,0.3); }
.wv-rd-flipbtn:hover { background: var(--button-dark); }
.wv-rd-main {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  background: var(--tag-bg);
  border: 1px solid var(--line);
}
.wv-rd-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--brand);
  font-size: var(--fs-3xl);
  opacity: 0.45;
}
.wv-rd-thumbs { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.wv-rd-thumb {
  width: 76px;
  height: 60px;
  object-fit: cover;
  cursor: pointer;
  border: 1px solid var(--line);
  opacity: 0.7;
  transition: opacity 0.15s ease, border-color 0.15s ease;
}
.wv-rd-thumb:hover { opacity: 1; }
.wv-rd-thumb.is-active { opacity: 1; border-color: var(--brand); }
/* Room-detail: photos carousel face */
.wv-rd-carousel, .wv-rd-carousel .carousel-inner, .wv-rd-carousel .carousel-item { width: 100%; height: 100%; }
.wv-rd-cimg { width: 100%; height: 100%; object-fit: cover; display: block; }
.wv-rd-carousel .carousel-control-prev, .wv-rd-carousel .carousel-control-next { width: 12%; }
.wv-rd-carousel .carousel-control-prev-icon, .wv-rd-carousel .carousel-control-next-icon { filter: drop-shadow(0 1px 3px rgba(0,0,0,0.6)); }
.wv-rd-carousel .carousel-indicators { margin-bottom: 0.6rem; z-index: 3; }
.wv-rd-carousel .carousel-indicators [data-bs-target] {
  width: 9px; height: 9px; border-radius: 50%; border: 0; margin: 0 4px;
  background: #fff; opacity: 0.55; box-shadow: 0 1px 3px rgba(0,0,0,0.5);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.wv-rd-carousel .carousel-indicators .active { opacity: 1; transform: scale(1.15); }
/* Room-detail: plan face with numbered markers + popover cards */
.wv-rd-plan { position: absolute; inset: 0; background: #eef1ec; }
.wv-rd-planimg { position: absolute; inset: 0; width: 100%; height: 100%; padding: 14px; box-sizing: border-box; object-fit: contain; display: block; }
.wv-rd-planbox { position: absolute; }

/* Room-list card media — plan (+ markers) by default, hover crossfades to the pooled photos.
   Sits above the card's stretched-link so its own click (open room modal) wins over "choose tenancy". */
.wv-room-card-media { position: relative; z-index: 2; aspect-ratio: 16 / 9; overflow: hidden; background: var(--tag-bg); border-bottom: 1px solid var(--line); cursor: pointer; }
.wv-rcm-plan { position: absolute; inset: 0; z-index: 0; background: #eef1ec; }
.wv-rcm-planimg { position: absolute; inset: 0; width: 100%; height: 100%; padding: 12px; box-sizing: border-box; object-fit: contain; display: block; }
.wv-rcm-planbox { position: absolute; pointer-events: none; }
.wv-rcm-zoom { position: absolute; bottom: 8px; right: 8px; z-index: 3; width: 30px; height: 30px; border-radius: 50%; border: none; background: var(--button); color: #fff; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 1px 5px rgba(0,0,0,0.22); transition: background 0.15s ease; }
.wv-rcm-zoom:hover { background: var(--button-dark); }
.wv-rcm-marker { position: absolute; transform: translate(-50%, -50%); width: 20px; height: 20px; border-radius: 50%; border: 2px solid #fff; background: var(--button); color: #fff; font-size: var(--fs-2xs); font-weight: 700; display: inline-flex; align-items: center; justify-content: center; box-shadow: 0 1px 4px rgba(0,0,0,0.4); }
.wv-rcm-photos { position: absolute; inset: 0; z-index: 1; opacity: 0; transition: opacity 0.4s ease; }
.wv-room-card-media.is-photobase .wv-rcm-photos { opacity: 1; }
.wv-room-card-media:hover .wv-rcm-photos { opacity: 1; }
.wv-rcm-photoimg { width: 100%; height: 100%; object-fit: cover; display: block; }
.wv-rcm-hint { position: absolute; left: 8px; bottom: 8px; z-index: 3; background: rgba(0,0,0,0.55); color: #fff; font-size: var(--fs-2xs); padding: 3px 7px; border-radius: 4px; pointer-events: none; transition: opacity 0.25s ease; }
.wv-room-card-media:hover .wv-rcm-hint { opacity: 0; }
.wv-rd-marker { position: absolute; transform: translate(-50%, -50%); width: 26px; height: 26px; border-radius: 50%; border: 2px solid #fff; background: var(--button); color: #fff; font-size: var(--fs-xs); font-weight: 700; line-height: 1; cursor: pointer; box-shadow: 0 1px 5px rgba(0,0,0,0.4); z-index: 2; display: inline-flex; align-items: center; justify-content: center; padding: 0; }
.wv-rd-marker:hover { background: var(--button-dark); }
.wv-rd-card { position: absolute; transform: translateX(-50%); width: min(240px, 72%); max-height: 80%; overflow: auto; background: #fff; border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 4px 18px rgba(0,0,0,0.28); padding: 8px; z-index: 5; }
.wv-rd-card-img { width: 100%; height: 120px; object-fit: cover; border-radius: 5px; display: block; }
.wv-rd-card-title { font-weight: 700; margin-top: 6px; font-size: var(--fs-sm); }
.wv-rd-card-cap { color: #6c757d; font-size: var(--fs-xs); margin-top: 2px; }
.wv-rd-card-nav { display: flex; align-items: center; justify-content: space-between; margin-top: 6px; font-size: var(--fs-xs); color: #6c757d; }
.wv-rd-card-nav button { background: none; border: none; font-size: var(--fs-lg); line-height: 1; cursor: pointer; color: var(--button); padding: 0 6px; }
.wv-rd-card-x { position: absolute; top: 2px; right: 6px; background: none; border: none; font-size: var(--fs-md); line-height: 1; cursor: pointer; color: #6c757d; z-index: 2; }
.wv-rd-info { padding-top: 0.25rem; }
.wv-rd-name { font-size: var(--fs-hero-sm); color: var(--ink); margin-bottom: 0.6rem; }
.wv-rd-specs { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.9rem; }
.wv-rd-spec {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--fs-sm);
  color: var(--ink);
  font-weight: 600;
}
.wv-rd-spec i { color: var(--brand); }
.wv-rd-price { color: var(--button); }
.wv-rd-price i { color: var(--button); }
.wv-rd-desc { color: #4a4a44; margin-bottom: 0.9rem; }
.wv-rd-tags { margin-top: 0; }
.wv-rd-aux-row { display: flex; flex-wrap: wrap; gap: 1.5rem; margin-top: 1.25rem; }
.wv-rd-aux { flex: 1 1 280px; min-width: 0; }
.wv-rd-aux-title {
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--brand);
  font-weight: 700;
  margin-bottom: 0.5rem;
}
.wv-rd-aux-title i { color: var(--brand); }
.wv-rd-floorplan, .wv-rd-video {
  width: 100%;
  border: 1px solid var(--line);
  background: var(--paper);
  display: block;
}
.wv-rd-aux-empty {
  border: 1px dashed var(--line);
  padding: 1rem;
  background: var(--paper);
}
@media (max-width: 768px) {
  .wv-rd-grid { grid-template-columns: 1fr; }
}

/* ---------- Floor plan modal ---------- */
:root {
  --wv-fp-dot-size:        16px;
  --wv-fp-flat-dot-size:   22px;
  --wv-fp-available:       #2ecc71;
  --wv-fp-sold:            #e74c3c;
  --wv-fp-partial:         #f39c12;
  --wv-fp-unknown:         #9aa0a6;
}

.wv-fp-modal .modal-header { gap: 1rem; align-items: center; }
.wv-fp-modal .modal-title  { display: flex; align-items: center; gap: 0.5rem; margin: 0; }
.wv-fp-modal .modal-body { position: relative; }
/* Option A ribbon: filter-style occupancy + matches chips, in a row under the modal title. */
.wv-fp-ribbon { flex: 0 0 auto; padding: 0.55rem 1rem; background: #f6f7f3; border-bottom: 1px solid var(--line); }
.wv-fp-modal .wv-fp-toolbar { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.wv-fp-ribbon-label { font-size: var(--fs-2xs); letter-spacing: 0.13em; text-transform: uppercase; font-weight: 800; color: #8b968c; }
.wv-fp-chips { display: inline-flex; gap: 0.4rem; flex-wrap: wrap; }
.wv-fp-chip { display: inline-flex; align-items: center; gap: 0.4rem; font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; color: var(--brand-dark); background: #fff; border: 1px solid var(--line); padding: 0.4rem 0.62rem; cursor: pointer; line-height: 1; }
.wv-fp-chip i { opacity: 0.6; }
.wv-fp-chip:hover { border-color: var(--brand); }
.wv-fp-chip.is-on { background: var(--brand); border-color: var(--brand); color: #fff; }
.wv-fp-chip.is-on i { opacity: 0.95; }
.wv-fp-chip--match.is-on { border-color: var(--accent-warm); background: var(--accent-warm); color: #fff; box-shadow: inset 0 0 0 1px var(--accent-warm); }
.wv-fp-chip--match.is-on i { opacity: 1; }
.wv-fp-ribbon-bar { width: 1px; height: 22px; background: var(--line); margin: 0 0.35rem; align-self: center; }

/* Option A community footer: identity + floor tags left, availability legend floated to the end. */
.wv-fp-footer { margin-top: 0.7rem; border-top: 2px solid var(--brand); padding-top: 0.7rem; }
.wv-fp-foot-row { display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap; }
.wv-fp-foot-chips { margin-top: 0.5rem; }
.wv-fp-foot-community { display: inline-flex; align-items: center; gap: 0.45rem; background: var(--brand); color: #fff; font-size: var(--fs-xs); font-weight: 800; letter-spacing: 0.03em; text-transform: uppercase; padding: 0.42rem 0.7rem; }
.wv-fp-foot-tag { display: inline-flex; align-items: center; gap: 0.32rem; font-size: var(--fs-xs); font-weight: 700; color: var(--brand-dark); background: #fff; border: 1.5px solid var(--tag-bg); padding: 0.3rem 0.55rem; }
.wv-fp-foot-tag i { color: var(--brand); }
.wv-fp-foot-legend { margin-left: auto; display: inline-flex; align-items: center; gap: 0.85rem; }
.wv-fp-foot-li { display: inline-flex; align-items: center; gap: 0.4rem; font-size: var(--fs-xs); color: var(--brand-dark); font-weight: 600; }
.wv-fp-glyph { width: 15px; height: 15px; flex: none; border: 2px solid; }
.wv-fp-glyph--available { background: var(--wv-fp-available); border-color: var(--wv-fp-available); }
.wv-fp-glyph--partial { background: linear-gradient(135deg, var(--wv-fp-partial) 0, var(--wv-fp-partial) 50%, #fff 50%, #fff 100%); border-color: var(--wv-fp-partial); }
.wv-fp-glyph--sold { background: #fff; border-color: var(--wv-fp-sold); position: relative; }
.wv-fp-glyph--sold::after { content: "\00d7"; position: absolute; inset: 0; display: grid; place-items: center; color: var(--wv-fp-sold); font-weight: 900; font-size: 0.7rem; line-height: 1; }
.wv-fp-foot-chipslabel { font-size: var(--fs-2xs); letter-spacing: 0.12em; text-transform: uppercase; font-weight: 800; color: #8b968c; }

/* Popover match explainer: shares-N-of-your-M meter + you-both-like chips + why. */
.wv-fp-mb { margin: 0.5rem 0 0.2rem; }
.wv-fp-mb-head { font-size: var(--fs-2xs); letter-spacing: 0.1em; text-transform: uppercase; font-weight: 700; color: #8b968c; margin-bottom: 0.35rem; }
.wv-fp-mb-tags { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.wv-fp-mb-match { display: flex; align-items: center; gap: 0.5rem; margin: 0.15rem 0 0.45rem; }
.wv-fp-mb-spark { width: 30px; height: 30px; flex: none; display: grid; place-items: center; background: var(--accent-warm); color: #fff; font-size: 0.9rem; }
.wv-fp-mb-mt { font-size: var(--fs-sm); font-weight: 800; color: var(--brand); line-height: 1.15; }
.wv-fp-mb-mt small { display: block; font-weight: 600; color: #6c757d; font-size: var(--fs-2xs); margin-top: 0.1rem; }
.wv-fp-mb-meter { display: flex; gap: 3px; margin-bottom: 0.15rem; }
.wv-fp-mb-meter i { height: 7px; flex: 1; background: #e7e3d8; }
.wv-fp-mb-meter i.on { background: var(--accent-warm); }
.wv-fp-mb-shared-lbl { font-size: var(--fs-2xs); letter-spacing: 0.1em; text-transform: uppercase; font-weight: 700; color: var(--accent-warm); margin: 0.55rem 0 0.32rem; }
.wv-fp-mb-rest-lbl { font-size: var(--fs-2xs); letter-spacing: 0.1em; text-transform: uppercase; font-weight: 700; color: #8b968c; margin: 0.55rem 0 0.32rem; }
.wv-fp-mb-shared .wv-tag { background: #ffe9df; color: #a23c1c; border: 1px solid var(--accent-warm); font-weight: 700; }
.wv-fp-frac { font-variant-numeric: tabular-nums; opacity: 0.7; font-weight: 700; }
.wv-fp-mb-why { font-size: var(--fs-xs); color: #6c757d; background: #f6f7f3; border-left: 3px solid var(--tag-bg, #bdbd89); padding: 0.45rem 0.55rem; margin-top: 0.5rem; }
.wv-fp-pop-price { font-size: var(--fs-lg); font-weight: 800; color: var(--brand); line-height: 1; margin: 0.15rem 0 0.55rem; }
.wv-fp-pop-price-unit { font-size: var(--fs-sm); font-weight: 600; color: #6c757d; }
.wv-fp-popover.popover { --bs-popover-max-width: 380px; max-width: 380px; }
.wv-fp-rail-badge { font-size: var(--fs-2xs); font-weight: 800; color: #fff; background: var(--wv-fp-available, #2ecc71); padding: 0.02rem 0.34rem; font-variant-numeric: tabular-nums; flex: none; }
.wv-fp-rail-badge--match { background: var(--accent-warm, #ff7844); }

.wv-fp-canvas {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 100%;
  max-height: 72vh;
  background: #f8f9fa;
  overflow: hidden;
}
/* Wrapper is sized in px by JS to the best fit of the image; the image fills it and the dots
   overlay (inset:0) matches the image box exactly. */
.wv-fp-img {
  display: block;
  width: 100%;
  height: 100%;
}
.wv-fp-dots { position: absolute; inset: 0; pointer-events: none; }
.wv-fp-dot {
  position: absolute;
  width: var(--wv-fp-dot-size); height: var(--wv-fp-dot-size);
  border-radius: 0;
  border: 2px solid white;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.4), 0 1px 3px rgba(0,0,0,0.3);
  transform: translate(-50%, -50%);
  cursor: pointer;
  padding: 0;
  pointer-events: auto;
  transition: transform 120ms;
}
.wv-fp-dot:hover, .wv-fp-dot:focus-visible {
  transform: translate(-50%, -50%) scale(1.2);
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
.wv-fp-dot--flat {
  width:  var(--wv-fp-flat-dot-size);
  height: var(--wv-fp-flat-dot-size);
  border-width: 3px;
}
.wv-fp-dot--available { background: var(--wv-fp-available); }
.wv-fp-dot--sold      { background: #fff; border-color: var(--wv-fp-sold); }
.wv-fp-dot--sold::after { content: "\00d7"; position: absolute; inset: 0; display: grid; place-items: center; color: var(--wv-fp-sold); font-weight: 900; font-size: 0.72rem; line-height: 1; }
.wv-fp-dot--partial   { background: linear-gradient(135deg, var(--wv-fp-partial) 0, var(--wv-fp-partial) 50%, #fff 50%, #fff 100%); }
.wv-fp-dot--other     { background: linear-gradient(135deg, var(--wv-fp-partial) 0, var(--wv-fp-partial) 50%, #fff 50%, #fff 100%); }
.wv-fp-dot--unknown   { background: var(--wv-fp-unknown); }
.wv-fp-dot--dim       { opacity: 0.35; }

/* Floor plan — social layer (Task 9) */
.wv-fp-social-bar { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.wv-fp-vibe-btn { font-size: var(--fs-xs); border: 1px solid currentColor; }
.wv-fp-social-hint, .wv-fp-match-legend { font-size: var(--fs-xs); opacity: 0.75; }
.wv-fp-match-toggle { font-size: var(--fs-xs); display: inline-flex; align-items: center; gap: 0.35rem; cursor: pointer; margin: 0; }
/* border-radius:50% needs !important to beat the global "* { border-radius:0 !important }" reset. */
.wv-fp-legend-dot { display: inline-block; width: 0.7em; height: 0.7em; border-radius: 50% !important; }
/* Match highlight: --bs-primary (dark green) vanishes against the green dots and olive plan art,
   so rings use the orange accent with a white separator, and the container dims non-matches. */
.wv-fp-dot--match-strong { box-shadow: 0 0 0 2px #fff, 0 0 0 5px var(--wv-fp-match, #f07c22), 0 0 12px 4px rgba(255, 120, 68, 0.55); transform: translate(-50%, -50%) scale(1.25); z-index: 3; }
.wv-fp-dot--match-some { box-shadow: 0 0 0 2px #fff, 0 0 0 4px color-mix(in srgb, var(--wv-fp-match, #f07c22) 55%, transparent); z-index: 2; }
.wv-fp-dots--matches .wv-fp-dot:not(.wv-fp-dot--match-strong):not(.wv-fp-dot--match-some) { opacity: 0.35; }
.wv-fp-legend-strong { background: var(--wv-fp-match, #f07c22); box-shadow: 0 0 0 2px #fff, 0 0 6px 2px rgba(255, 120, 68, 0.5); }
.wv-fp-legend-some { background: color-mix(in srgb, var(--wv-fp-match, #f07c22) 55%, transparent); box-shadow: 0 0 0 2px #fff; }
.wv-fp-pop-socialblock { margin-top: 0.6rem; border-top: 1px solid #eee; padding-top: 0.6rem; }
.wv-fp-pop-community { display: flex; align-items: center; gap: 0.45rem; background: var(--bs-primary, #37543b); color: #fff; padding: 0.35rem 0.6rem; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; margin-bottom: 0.5rem; }
.wv-fp-pop-social { margin-top: 0.4rem; display: flex; flex-wrap: wrap; gap: 0.25rem; align-items: baseline; }
.wv-fp-pop-social-head { font-size: var(--fs-xs); opacity: 0.7; width: 100%; }
.wv-fp-pop-social .wv-tag { font-size: var(--fs-xs); }
.wv-fp-pop-social .wv-social-chip-ico { width: 18px; height: 18px; }
.wv-fp-match-badge { background: var(--wv-fp-match, #f07c22); color: #fff; font-size: var(--fs-xs); }
.wv-fp-match-badge--some { background: rgba(255, 120, 68, 0.6); }
.wv-fp-floorstrip { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.wv-fp-floorstrip-community { display: inline-flex; align-items: center; gap: 0.45rem; background: var(--bs-primary, #37543b); color: #fff; padding: 0.3rem 0.6rem; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; }
.wv-fp-floorstrip-chips { display: inline-flex; align-items: center; gap: 0.3rem; flex-wrap: wrap; }
.wv-fp-floorstrip-chips .wv-tag { font-size: var(--fs-xs); }
.wv-fp-floorstrip .wv-social-chip-ico { width: 16px; height: 16px; }
/* 404 — server /notfound page and in-page data misses (wvRenderNotFound) share this. */
.wv-social-desc-badges { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-top: 0.3rem; justify-content: inherit; }
.wv-social-badge { font-size: var(--fs-xs); font-weight: 600; padding: 0.1rem 0.4rem; letter-spacing: 0.03em; background: #6c757d; color: #fff; white-space: nowrap; }
.wv-social-swatch { width: 14px; height: 14px; display: inline-block; border: 1px solid rgba(0, 0, 0, 0.25); }
.wv-social-desc-badges { justify-content: center; }
.wv-social-desc-pop .wv-social-desc-badges { justify-content: flex-start; }
.wv-nf-main { display: flex; justify-content: center; padding: 4rem 1rem 6rem; }
.wv-notfound { text-align: center; max-width: 480px; }
.wv-nf-plan { display: grid; grid-template-columns: repeat(6, 18px); gap: 6px; justify-content: center; margin-bottom: 1.5rem; }
.wv-nf-plan span { width: 18px; height: 18px; background: #e3e0d6; border: 1px solid rgba(0, 0, 0, 0.08); }
.wv-nf-plan .is-here { background: var(--wv-fp-match, #f07c22); box-shadow: 0 0 0 2px #fff, 0 0 10px 3px rgba(255, 120, 68, 0.5); }
.wv-nf-code { font-size: var(--fs-xs); letter-spacing: 0.3em; opacity: 0.5; margin-bottom: 0.25rem; }
.wv-nf-title { font-size: var(--fs-2xl); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 0.5rem; }
.wv-nf-copy { font-size: var(--fs-sm); opacity: 0.8; }
.wv-nf-ctas { display: flex; gap: 0.6rem; justify-content: center; margin-top: 1.25rem; flex-wrap: wrap; }
/* Social picker modal */
/* Interest picker: icon chips in sentence case (the vocab is 200+ values — icons carry the scanning),
   cap squares fill orange as you pick, and a category dims once its cap is reached. */
.wv-social-cat { margin-bottom: 1.25rem; }
.wv-social-cat-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; border-bottom: 1px solid rgba(0, 0, 0, 0.1); padding-bottom: 0.3rem; margin-bottom: 0.6rem; }
.wv-social-cat-name { font-size: var(--fs-sm); font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--bs-primary, #37543b); }
.wv-social-cat-meta { display: inline-flex; align-items: center; gap: 0.5rem; }
.wv-social-cat-hint { font-size: var(--fs-sm); opacity: 0.7; }
.wv-social-cap-squares { display: inline-flex; gap: 3px; padding: 3px; background: rgba(0, 0, 0, 0.07); border: 1px solid rgba(0, 0, 0, 0.1); }
.wv-social-cap-square { width: 14px; height: 14px; background: #fff; border: 1px solid rgba(0, 0, 0, 0.12); }
.wv-social-cap-square.is-filled { background: var(--wv-fp-match, #f07c22); border-color: var(--wv-fp-match, #f07c22); }
.wv-social-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.wv-social-chip { display: inline-flex; align-items: center; gap: 0.45rem; padding: 0.3rem 0.7rem 0.3rem 0.45rem; border: 1px solid rgba(0, 0, 0, 0.18); background: #fff; color: inherit; font-size: var(--fs-sm); text-transform: none; letter-spacing: normal; line-height: 1.2; cursor: pointer; }
.wv-social-chip:hover:not(:disabled) { border-color: var(--bs-primary, #37543b); }
.wv-social-chip.is-selected { background: color-mix(in srgb, var(--tag-bg, #bdbd89) 30%, #fff); border-color: var(--brand, #37543b); box-shadow: inset 0 0 0 1px var(--brand, #37543b); }
.wv-social-chip.is-selected::after { content: "\2713"; margin-left: 0.15rem; color: var(--brand, #37543b); font-weight: 700; }
.wv-social-chip:disabled { opacity: 0.35; cursor: default; }
.wv-social-chip-ico { width: 20px; height: 20px; object-fit: contain; flex: 0 0 auto; }

.wv-social-view { display: none; margin-left: auto; margin-right: 0.75rem; }
.wv-social-view .btn { font-size: var(--fs-xs); padding: 0.2rem 0.7rem; }
#wv-social-picker .modal-xl { max-width: min(1320px, 94vw); }
.wv-social-cards--row { display: flex; gap: 0.5rem; overflow-x: auto; padding-bottom: 0.5rem; scroll-snap-type: x proximity; }
.wv-social-cards--row .wv-social-card { flex: 0 0 175px; scroll-snap-align: start; }
.wv-social-card { position: relative; border: 1px solid rgba(0, 0, 0, 0.18); background: #fff; color: inherit; padding: 0.6rem 0.5rem; text-align: center; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: 0.35rem; text-transform: none; letter-spacing: normal; }
.wv-social-card img { width: 44px; height: 44px; object-fit: contain; }
.wv-social-card b { font-size: var(--fs-base); line-height: 1.2; }
.wv-social-card p { font-size: var(--fs-sm); opacity: 0.7; margin: 0; line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
/* Long categories: full-length columns side by side — the modal body is the ONLY vertical scroll;
   sticky column heads keep the cap squares in view. */
.wv-social-columns { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.9rem; align-items: start; }
@media (max-width: 900px) { .wv-social-columns { grid-template-columns: repeat(2, 1fr); } }
.wv-social-col-head { position: sticky; top: 0; z-index: 2; background: #fff; display: flex; flex-direction: column; align-items: flex-start; gap: 0.2rem; border-bottom: 1px solid rgba(0, 0, 0, 0.1); padding: 0.3rem 0; margin-bottom: 0.45rem; }
.wv-social-col-list { display: flex; flex-direction: column; gap: 0.3rem; height: min(44vh, 500px); overflow-y: auto; scrollbar-width: none; }
.wv-social-col-list::-webkit-scrollbar { display: none; }
.wv-social-col-arrow { display: flex; align-items: center; justify-content: center; width: 100%; padding: 0.18rem 0; border: 1px solid #d6d6d6; border-radius: 2px; background: #fff; color: var(--brand-dark, #37543b); cursor: pointer; font-size: var(--fs-xs); line-height: 1; transition: border-color 0.15s ease, color 0.15s ease, opacity 0.15s ease; margin: 0.15rem 0; }
.wv-social-col-arrow:hover:not(:disabled) { border-color: var(--brand, #37543b); color: var(--brand, #37543b); }
.wv-social-col-arrow:disabled { opacity: 0.3; cursor: default; }
.wv-social-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.32rem 0.5rem; border: 1px solid rgba(0, 0, 0, 0.14); background: #fff; color: inherit; font-size: var(--fs-sm); text-transform: none; letter-spacing: normal; text-align: left; line-height: 1.25; cursor: pointer; }
.wv-social-row img { width: 24px; height: 24px; object-fit: contain; flex: 0 0 auto; }
.wv-social-row:hover:not(:disabled) { border-color: var(--bs-primary, #37543b); }
.wv-social-row.is-selected { background: color-mix(in srgb, var(--tag-bg, #bdbd89) 30%, #fff); border-color: var(--brand, #37543b); box-shadow: inset 0 0 0 1px var(--brand, #37543b); }
.wv-social-row.is-selected::after { content: "\2713"; margin-left: auto; color: var(--brand, #37543b); font-weight: 700; }
.wv-social-row:disabled { opacity: 0.35; cursor: default; }
.wv-social-card:hover:not(:disabled) { border-color: var(--bs-primary, #37543b); }
.wv-social-card.is-selected { background: color-mix(in srgb, var(--tag-bg, #bdbd89) 30%, #fff); border: 2px solid var(--brand, #37543b); padding: calc(0.6rem - 1px) calc(0.5rem - 1px); }
.wv-social-card.is-selected::after { content: "\2713"; position: absolute; top: 0; right: 0; width: 1.25rem; height: 1.25rem; background: var(--brand, #37543b); color: #fff; font-size: var(--fs-xs); display: flex; align-items: center; justify-content: center; }
.wv-social-card:disabled { opacity: 0.35; cursor: default; }
.wv-social-desc-pop.wv-social-desc-pop--rich { width: min(500px, 92vw); display: block; }
.wv-social-pop-hint { font-size: var(--fs-xs); opacity: 0.65; border-top: 1px solid rgba(0, 0, 0, 0.1); padding-top: 0.5rem; margin-top: 0.6rem; }
.wv-social-pop-head { background: #fff; color: var(--brand, #37543b); font-family: "Rotonto", "Mulish", "Century Gothic", system-ui, sans-serif; font-weight: 400; text-transform: uppercase; letter-spacing: 0.02em; font-size: var(--fs-md); padding: 0.55rem 0.8rem; border-bottom: 1px solid var(--line, #d6d3c9); margin: -0.7rem -0.8rem 0.7rem; }
.wv-social-info-rows { display: flex; flex-direction: column; gap: 0.65rem; margin: 0.6rem 0; font-size: var(--fs-sm); }
.wv-social-info-item { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.wv-social-info-line { display: flex; align-items: center; gap: 0.5rem; flex: 0 0 auto; }
.wv-social-info-item p { margin: 0; opacity: 0.8; }
.wv-social-desc-pop--rich p { margin-bottom: 0.45rem; }
.wv-social-info { border: 0; background: none; color: var(--brand, #37543b); opacity: 0.55; font-size: var(--fs-base); padding: 0 0.2rem; cursor: help; vertical-align: middle; }
.wv-social-info:hover, .wv-social-info:focus { opacity: 1; }
.wv-social-desc-pop { position: fixed; z-index: 1080; width: 280px; background: #fff; border: 1px solid rgba(0, 0, 0, 0.2); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18); padding: 0.7rem 0.8rem; display: flex; gap: 0.65rem; align-items: flex-start; pointer-events: none; }
.wv-social-desc-pop img { width: 44px; height: 44px; object-fit: contain; flex: 0 0 auto; }
.wv-social-pop-side { display: flex; flex-direction: column; align-items: center; gap: 0.35rem; flex: 0 0 auto; }
.wv-social-pop-side .wv-social-desc-badges { justify-content: center; margin-top: 0; }
.wv-social-desc-pop b { font-size: var(--fs-base); display: block; margin-bottom: 0.15rem; }
.wv-social-desc-pop p { font-size: var(--fs-sm); margin: 0; opacity: 0.75; line-height: 1.35; }
.wv-social-footer { display: flex; align-items: center; }
.wv-social-count { font-size: var(--fs-xs); opacity: 0.7; margin-right: auto; }
.wv-social-intro { font-size: var(--fs-base); }
.wv-social-share { margin-top: 1rem; border-top: 1px solid rgba(0, 0, 0, 0.1); padding: 0.9rem 0 0 0; display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.wv-social-share-label { font-size: var(--fs-base); display: flex; gap: 0.5rem; align-items: flex-start; }
.wv-social-share-label i { margin-top: 0.25rem; }
.wv-social-share-lines { display: flex; flex-direction: column; gap: 0.1rem; }
.wv-social-share-sub { font-size: var(--fs-xs); opacity: 0.65; }
.wv-social-share-label i { color: var(--brand, #37543b); opacity: 0.6; margin-right: 0.3rem; }
.wv-social-share-group .btn { font-size: var(--fs-sm); padding: 0.25rem 1.1rem; }
.wv-social-share-state { font-size: var(--fs-xs); opacity: 0.7; }
.wv-social-identity-card { margin: 0 0 1.25rem; }

.wv-matched { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; margin: 0.5rem 0; }
.wv-matched-badge { font-size: var(--fs-xs); font-weight: 700; padding: 0.15rem 0.5rem; background: var(--bs-primary, #4c6fff); color: #fff; }
.wv-matched-badge--some { opacity: 0.7; }
.wv-matched-copy { font-size: var(--fs-xs); }

.wv-fp-loading, .wv-fp-placeholder {
  text-align: center;
  color: #666;
  padding: 3rem 1rem;
}

/* Floor plan popovers */
.popover.wv-fp-popover { max-width: 360px; width: max-content; }
.wv-fp-popover .popover-body { padding: 0.75rem; }
.wv-fp-popover .popover-header { background: transparent; border-bottom: 1px solid #eee; display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.wv-fp-popover .wv-fp-pop-title-name { min-width: 0; }
.wv-fp-badge-other { background: #f39c12; color: #fff; }
.wv-fp-pop-othernote { color: #b3401e; }
.wv-fp-popover--sold .popover-header,
.wv-fp-popover--sold .wv-fp-pop-body { color: #888; }
.wv-fp-popover--sold .wv-fp-pop-tag { opacity: 0.6; }
.wv-fp-pop-tags { display: flex; flex-wrap: wrap; gap: 0.25rem; }
/* Same chip language as .wv-tag (olive) — section context distinguishes room facts from interests. */
.wv-fp-pop-tag {
  display: inline-flex; align-items: center; gap: 0.25rem;
  font-size: var(--fs-xs); padding: 0.15rem 0.4rem;
}
.wv-fp-pop-tag i { font-size: var(--fs-2xs); }
.wv-fp-view-toggle .btn { font-size: var(--fs-sm); }
.wv-fp-view-toggle .btn i { margin-right: 0.25rem; }

/* Canvas + vertical floor rail (rail appears only when a building has >1 floor with a plan) */
.wv-fp-stage { display: flex; gap: 0.75rem; align-items: stretch; }
.wv-fp-canvas-host { flex: 1; min-width: 0; position: sticky; top: 0; align-self: flex-start; }
.wv-fp-rail {
  display: flex; flex-direction: column; gap: 0.35rem;
  width: 8.5rem; flex: 0 0 auto;
  padding-right: 0.15rem;
}
.wv-fp-rail-btn {
  display: flex; flex-direction: column; gap: 0.35rem;
  padding: 0.35rem; border: 1px solid #dee2e6; border-radius: 8px;
  background: #fff; color: inherit; cursor: pointer; font-size: var(--fs-sm); text-align: left;
  transition: background 120ms, border-color 120ms, color 120ms;
}
.wv-fp-rail-btn:hover { background: #f1f3f5; }
.wv-fp-rail-btn.active { background: var(--brand); border-color: var(--brand); color: #fff; }
.wv-fp-rail-thumb {
  width: 100%; height: 4.5rem; object-fit: contain; display: block;
  border-radius: 4px; background: #f1f3f5; border: 1px solid rgba(0,0,0,0.06);
}
.wv-fp-rail-row { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.wv-fp-rail-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wv-fp-rail-count {
  background: rgba(0,0,0,0.08); border-radius: 999px; padding: 0 0.45rem;
  font-size: var(--fs-xs); font-weight: 600;
}
.wv-fp-rail-btn.active .wv-fp-rail-count { background: rgba(255,255,255,0.3); }

/* Zoom + pan: single transform on the wrapper, dots track it; controls overlay top-right */
/* Sized in px by JS to the fitted image box; inline-block so it wraps the image tightly (dots
   align). No will-change/translateZ: a promoted GPU layer rasterises at display size then scales
   up (blurry); plain transform re-rasterises from source on zoom (crisp). */
.wv-fp-zoomwrap { position: relative; display: inline-block; line-height: 0; transform-origin: 0 0; }
.wv-fp-canvas.wv-fp-zoomed { cursor: grab; }
.wv-fp-canvas.wv-fp-panning { cursor: grabbing; }
.wv-fp-zoom-controls {
  position: absolute; top: 0.5rem; right: 0.5rem; z-index: 5;
  display: flex; flex-direction: column; gap: 0.25rem;
}
.wv-fp-zoom-btn {
  width: 2rem; height: 2rem; border: 1px solid #dee2e6; border-radius: 6px;
  background: rgba(255,255,255,0.95); cursor: pointer; display: flex;
  align-items: center; justify-content: center; font-size: var(--fs-sm); color: #333;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.wv-fp-zoom-btn:hover { background: #fff; }

/* Floor-plan trigger button (operator CTA rust — matches .btn-primary / Continue) */
.wv-fp-trigger-btn {
  background: var(--button); border: 1px solid var(--button); color: #fff; white-space: nowrap;
}
.wv-fp-trigger-btn:hover { background: var(--button-dark); border-color: var(--button-dark); color: #fff; }
.wv-fp-trigger-btn i { margin-right: 0.35rem; }

/* Per-card floor plan link */
.wv-card-fp-link { padding-left: 0.25rem; }
.wv-card-fp-link a { color: var(--brand); }
.wv-card-fp-link a:hover { text-decoration: underline; }
.wv-card-fp-link i { margin-right: 0.25rem; }

@media (max-width: 575.98px) {
  .wv-fp-modal .modal-header { flex-wrap: wrap; row-gap: 0.5rem; }
  .wv-fp-modal .wv-fp-toolbar { width: 100%; order: 3; }
  .wv-fp-stage { flex-direction: column; }
  .wv-fp-rail { width: 100%; flex-direction: row; flex-wrap: wrap; max-height: none; }
}

/* Profile photo button (in the full-name field area) — click to upload; bg removed server-side */
/* Photo column stretches to the height of the two field rows on its right (outer flex = stretch);
   the button fills it as a rounded rectangle. */
.wv-photo-col { flex: 0 0 auto; width: 132px; align-self: stretch; }
.wv-photo-btn {
  position: relative; width: 100%; height: 100%; min-height: 120px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line, #d6d3c9); padding: 0; border-radius: 12px;
  background: #ece9e0; cursor: pointer; overflow: hidden;
}
.wv-photo-btn img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.wv-photo-placeholder { font-size: 84px; /* fs-allow: large placeholder glyph, not text */ line-height: 1; color: var(--brand); }
.wv-photo-cam { position: absolute; right: 6px; bottom: 6px; width: 34px; height: 34px; border-radius: 50%; background: var(--brand); color: #fff; display: flex; align-items: center; justify-content: center; font-size: var(--fs-sm); border: 2px solid var(--paper, #fff); z-index: 2; }
.wv-photo-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.45); display: flex; align-items: center; justify-content: center; color: #fff; z-index: 3; }
.wv-photo-btn.is-busy { cursor: default; }

/* Nationality dropdown — selected item in brand green (not Bootstrap blue) */
.wv-nat .dropdown-item.active, .wv-nat .dropdown-item:active { background-color: var(--brand); color: #fff; }
.wv-nat .dropdown-item:hover:not(.active) { background-color: rgba(55,84,59,0.10); }

/* Group "Your flatmates" progress panel (group-panel.js) */
.wv-grp-panel { border: 1px solid var(--line, #d6d3c9); border-radius: 0.9rem; padding: 1.25rem 1.5rem; background: var(--paper, #fff); margin: 1.5rem 0; max-width: 720px; }
.wv-grp-member { padding: 0.75rem 0; border-top: 1px solid var(--line, #eeece4); }
.wv-grp-member:first-of-type { border-top: none; padding-top: 0; }
.wv-grp-member-head { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.wv-grp-pills { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
.wv-grp-pill { display: inline-flex; align-items: center; gap: 0.3rem; font-size: var(--fs-xs); color: #9a988e; padding: 0.15rem 0.55rem; border: 1px solid var(--line, #e3e1d8); border-radius: 999px; }
.wv-grp-pill.on { color: #fff; background: var(--brand, #37543b); border-color: var(--brand, #37543b); }
.wv-grp-badge { font-size: var(--fs-xs); padding: 0.1rem 0.5rem; border-radius: 999px; margin-left: auto; }
.wv-grp-badge.invited { color: #8a6d3b; background: #fcf3df; }
.wv-grp-badge.declined { color: #a14d3d; background: #f7e7e3; }

/* Identity step — two balanced selection cards; the chosen method's flow renders in a full-width
   panel underneath, so the selection cards stay equal height. */
.wv-id-card { cursor: pointer; transition: border-color 120ms, box-shadow 120ms; }
.wv-id-card:hover { border-color: var(--brand); }
.wv-id-card.active { border-color: var(--brand); box-shadow: 0 0 0 2px rgba(55,84,59,0.25); }
.wv-id-card-icon { font-size: var(--fs-xl); color: var(--brand); line-height: 1; }
/* In-card result slot collapses when empty so the flow card isn't padded out by a blank area. */
.wv-flow-result:empty { display: none; }
/* Yoti renders its own card on a light-grey page background inside the (cross-origin) frame, which
   shows as grey bands beside the centred card. We can't recolour that, so instead we constrain the
   iframe to roughly the card width and centre it on a white, green-bordered wrapper — the white
   wrapper fills the sides and the grey is clipped at the iframe edge. */
.wv-yoti-wrap {
  background: #fff;
  border: 1px solid var(--brand);
  border-radius: 8px;
  box-shadow: 0 0 0 2px rgba(55,84,59,0.25);
  padding: 1.25rem;
}
.wv-yoti-iframe {
  display: block;
  margin: 0 auto;
  max-width: 820px;
}

/* Supporting-documents upload — drag-drop zone + file rows. */
.wv-dropzone {
  border: 2px dashed #b3af9f;
  border-radius: 12px;
  background: var(--paper, #fff);
  padding: 2rem 1rem;
  text-align: center;
  cursor: pointer;
  color: #6c757d;
  transition: border-color .15s, background-color .15s, color .15s;
}
.wv-dropzone:hover, .wv-dropzone.is-drag {
  border-color: var(--brand);
  background: rgba(55, 84, 59, 0.05);
  color: var(--brand);
}
.wv-dropzone i { font-size: var(--fs-xl); margin-bottom: .5rem; }
.wv-dropzone p { margin: 0; }
.wv-dropzone-link { color: var(--brand); text-decoration: underline; }
/* Document type-tag dropdown: button + menu share one fixed width so they line up. */
.wv-type-dd { display: inline-block; min-width: 13rem; }
.wv-type-dd > .dropdown-toggle { width: 100%; display: inline-flex; align-items: center; justify-content: space-between; }
.wv-type-dd .dropdown-menu { width: 100%; min-width: 100%; }
.wv-doc-thumb {
  width: 44px; height: 44px; border-radius: 8px; object-fit: cover; flex: 0 0 auto; background: #f1efe9;
}
.wv-doc-thumb-icon {
  width: 44px; height: 44px; border-radius: 8px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  background: #f1efe9; color: var(--brand); font-size: var(--fs-md);
}

/* No dividing line into the header; a light band (a touch lighter than the sage page) sits under it. */
#wv-chrome { border-bottom: none; }
.wv-site-navbar { background: #EFEEE6; padding: 0.55rem calc(1rem + clamp(1rem, 3vw, 2.5rem)); }
/* margin-left cancels the first link's padding so its text lines up with the logo above. */
.wv-site-nav { display: flex; gap: 1.5rem; align-items: center; margin-left: -0.5rem; }
/* Same treatment as the buttons — body font, UPPERCASE, tight tracking, semibold — but brand green,
   not rust. Subtle box highlight on hover (like the account name). */
.wv-nav-link { font-family: inherit; }
.wv-site-nav .wv-nav-link { text-decoration: none; color: var(--brand); font-weight: 600; font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.1em; padding: 0.2rem 0.5rem; border-radius: 4px; transition: background .12s ease, color .12s ease; }
.wv-site-nav .wv-nav-link:hover { background: rgba(0, 0, 0, 0.06); color: var(--brand-dark); }
/* Building chapter bar — full-bleed band under the hero, above the breadcrumb: the site nav
   strip's twin (same putty band + link treatment), scoped to this building's pages. */
.wv-building-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.5rem;
  /* Full-bleed band whose LINKS stay on the content column (level with the breadcrumb): the
     negative side margins and the side padding are the same length, so the text never moves even
     when the booking card reserves the right gutter and main stops being viewport-centred. */
  margin: 0 calc((100% - 100vw) / 2) 1.25rem;
  padding: 0.55rem calc((100vw - 100%) / 2);
  background: #EFEEE6;
}
.wv-building-nav .wv-nav-link:first-child { margin-left: -0.5rem; }
.wv-building-nav:empty { display: none; }
/* Snug against the hero's 2rem bottom margin when a hero precedes it. */
main:has(> .hero) > .wv-building-nav { margin-top: -2rem; }
.wv-building-nav .wv-nav-link {
  text-decoration: none;
  color: var(--brand);
  font-weight: 600;
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding: 0.2rem 0.5rem;
  border-radius: 4px;
  transition: background .12s ease, color .12s ease;
}
.wv-building-nav .wv-nav-link:hover { background: rgba(0, 0, 0, 0.06); color: var(--brand-dark); }
/* Profile "Your interests" - section head with its action, picker-scale chips. */
.wv-interests-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
#interests-chips .wv-tag { font-size: var(--fs-sm); padding: 0.3rem 0.6rem; }
#interests-chips .wv-social-chip-ico { width: 22px; height: 22px; }
/* Form labels read at sm across the portal - Bootstrap's .small was shrinking them to whisper size. */
.form-label, .form-label.small { font-size: var(--fs-sm); }
/* Profile interests grouped by category, picker-order. */
#interests-chips { display: flex; flex-wrap: wrap; gap: 0.9rem 1.8rem; }
.wv-interests-group { display: flex; flex-direction: column; gap: 0.35rem; }
.wv-interests-cat { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--brand, #37543b); opacity: 0.85; }
.wv-interests-tags { display: flex; flex-wrap: wrap; gap: 0.4rem; }
#interests-chips .wv-tag { font-size: var(--fs-sm); padding: 0.35rem 0.65rem; }
#interests-chips .wv-social-chip-ico { width: 24px; height: 24px; }
/* Change Request type picker (manage booking) - same selection language as the interests picker. */
.wv-mb-change-types { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
.wv-mb-change-type { display: flex; gap: 0.6rem; align-items: flex-start; padding: 0.55rem 0.7rem; border: 1px solid rgba(0, 0, 0, 0.14); background: #fff; color: inherit; text-align: left; text-transform: none; letter-spacing: normal; font-size: var(--fs-sm); cursor: pointer; }
.wv-mb-change-type i { color: var(--brand, #37543b); margin-top: 0.2rem; }
.wv-mb-change-type span { display: flex; flex-direction: column; gap: 0.1rem; }
.wv-mb-change-type small { font-size: var(--fs-xs); opacity: 0.7; }
.wv-mb-change-type:hover { border-color: var(--brand, #37543b); }
.wv-mb-change-type.is-selected { background: color-mix(in srgb, var(--tag-bg, #bdbd89) 30%, #fff); border-color: var(--brand, #37543b); box-shadow: inset 0 0 0 1px var(--brand, #37543b); }
/* Hoverable interest chips advertise their popover. */
.wv-tag[data-val] { cursor: pointer; }
/* Floor strip sits under the plan; the interests button floats to the row end. */
.wv-fp-floorstrip { margin: 0.6rem 0 0; }
.wv-fp-floorstrip .wv-fp-vibe-btn { margin-left: auto; }
/* Wheel/touch past a modal's scroll end must not chain to the page behind it. */
.modal .modal-body { overscroll-behavior: contain; }
/* The plan image must never start a native drag - pointer panning owns the gesture. */
.wv-fp-img { -webkit-user-drag: none; user-select: none; }
/* Room-type card: availability badge over the image; price line prominent under the title. */
.wv-card-media { position: relative; }
/* Image-corner status chips — one family with .wv-coming-soon-banner (restyled to match). */
.wv-avail-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.28rem 0.65rem;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
}
.wv-avail-badge--soldout { background: #c8353f; color: #fff; }
.wv-avail-badge--low { background: var(--accent-warm, #ff7844); color: #1d1d1b; }
.wv-avail-badge--good { background: var(--tag-bg, #bdbd89); color: var(--brand, #37543b); }
/* "Also available" budget chip — one overlay combining the price near-miss reason + delta,
   bottom-left of the card image (the availability badge sits top-left). */
.wv-budget-badge {
  position: absolute;
  bottom: 0.6rem;
  left: 0.6rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.28rem 0.6rem;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.2;
}
.wv-budget-badge--over { background: var(--accent-warm, #ff7844); color: #1d1d1b; }
.wv-budget-badge--under { background: var(--tag-bg, #bdbd89); color: var(--brand, #37543b); }
.wv-excluded-by .wv-budget-badge { position: static; }  /* no-image fallback: in-flow, not overlaid */
.wv-card-price { font-size: var(--fs-md); font-weight: 600; color: var(--brand, #37543b); }
.wv-card-price .muted { font-size: var(--fs-sm); font-weight: 400; }

/* Room-picker card price — the hero figure: brand green + large, with a muted /wk suffix. */
.wv-room-price { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.1rem; }
.wv-room-price-amt { font-size: var(--fs-xl); font-weight: 800; color: var(--brand, #37543b); line-height: 1; }
.wv-room-price-per { font-size: var(--fs-sm); font-weight: 500; color: #888; }
.wv-room-price-sub { font-size: var(--fs-sm); color: #888; width: 100%; }
/* Building-card blurb (CMS hero description) clamped to three lines. */
.wv-card-blurb { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
/* Enquiry thank-you: brand-toned, matching the site's uppercase green headings. */
.wv-enquiry-done { padding: 0.75rem 0; }
.wv-enquiry-done .fa-circle-check { color: var(--brand, #37543b); }
.wv-enquiry-done-title { text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; color: var(--brand, #37543b); font-size: var(--fs-md); }
.wv-enquiry-done-sub { color: #6c6c64; font-size: var(--fs-sm); }
/* City building cards: quiet location line and a rust action cue bottom-right. */
.wv-card-locale { color: #6c6c64; font-size: var(--fs-sm); }
.wv-card-locale i { color: var(--button, #a14d3d); margin-right: 0.25rem; }
.wv-card-cta { color: var(--button, #a14d3d); font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; font-size: var(--fs-xs); }
.wv-card-cta i { transition: transform 0.15s ease; }
a.card:hover .wv-card-cta i { transform: translateX(3px); }
/* Tag-group headings on cards (same voice as the profile interests categories), tight to their chips. */
.wv-tags-head { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink, #1d1d1b); margin: 0.75rem 0 0.3rem; }
.wv-tags-head + .wv-tags { margin-top: 0; }
/* Building hero: strapline sits under the name, same display face, a step smaller. */
.hero-text h1 .wv-hero-strap { display: block; font-size: 0.6em; margin-top: 0.4rem; }
/* Hero CTAs sit level with the last line of the tagline (1rem = the paragraph's own bottom margin;
   the buttons carried a stray bottom margin that floated them above it). */
#hero-cta { bottom: 1rem; margin: 0 !important; }
/* Title-row card buttons (View Floor Plans / Join waitlist) share one width so cards align. */
.wv-card-h-col .wv-fp-trigger-btn { min-width: 200px; display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem; }
/* Hero CTAs (Book a viewing / View Floor Plans) share one width. */
#hero-cta .btn { min-width: 200px; display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem; }
/* Labels hug their inputs (Bootstrap's default 0.5rem reads as floating too high). */
.form-label { margin-bottom: 0.2rem; }
/* The What's-nearby category bar builds the single-row chipbar markup directly. */
.wv-locale-chipbar { flex-direction: row; gap: 0.4rem; min-height: 52px; }
/* Coming-soon cards are dimmed, but their lead-capture must read and click at full strength. */
.wv-card-coming-soon .wv-interest { opacity: 1; }
/* Signal icons carry the life instead of the old blue dot: the eye blinks, the trend arrow
   nudges upward, the flame flickers. Stilled by the prefers-reduced-motion rule above. */
@keyframes wvEyeBlink { 0%, 90%, 100% { transform: scaleY(1); } 95% { transform: scaleY(0.08); } }
.wv-signal-live i { animation: wvEyeBlink 3.4s ease-in-out infinite; transform-origin: center; }
@keyframes wvTrendDraw {
  0%   { clip-path: inset(-2px 100% -2px 0); opacity: 1; }
  35%  { clip-path: inset(-2px 0 -2px 0); opacity: 1; }
  88%  { clip-path: inset(-2px 0 -2px 0); opacity: 1; }
  92%  { clip-path: inset(-2px 0 -2px 0); opacity: 0; }
  96%  { clip-path: inset(-2px 100% -2px 0); opacity: 0; }
  100% { clip-path: inset(-2px 100% -2px 0); opacity: 1; }
}
.wv-signal-velocity i { animation: wvTrendDraw 3s ease-in-out infinite; }
@keyframes wvFlameFlicker {
  0%   { transform: scaleY(1) scaleX(1) rotate(0deg); opacity: 1; }
  7%   { transform: scaleY(1.09) scaleX(0.94) rotate(-2deg); opacity: 0.88; }
  13%  { transform: scaleY(0.96) scaleX(1.03) rotate(1deg); opacity: 1; }
  22%  { transform: scaleY(1.13) scaleX(0.9) rotate(-1deg); opacity: 0.8; }
  27%  { transform: scaleY(1.02) scaleX(0.98) rotate(2.5deg); opacity: 0.96; }
  38%  { transform: scaleY(0.93) scaleX(1.06) rotate(-0.5deg); opacity: 0.9; }
  44%  { transform: scaleY(1.07) scaleX(0.95) rotate(-2.5deg); opacity: 1; }
  51%  { transform: scaleY(1.01) scaleX(1) rotate(1.5deg); opacity: 0.85; }
  63%  { transform: scaleY(1.11) scaleX(0.92) rotate(0.5deg); opacity: 0.93; }
  71%  { transform: scaleY(0.95) scaleX(1.04) rotate(-1.5deg); opacity: 1; }
  78%  { transform: scaleY(1.05) scaleX(0.97) rotate(2deg); opacity: 0.82; }
  86%  { transform: scaleY(0.98) scaleX(1.01) rotate(-2.2deg); opacity: 0.95; }
  93%  { transform: scaleY(1.08) scaleX(0.94) rotate(1.2deg); opacity: 0.9; }
  100% { transform: scaleY(1) scaleX(1) rotate(0deg); opacity: 1; }
}
.wv-signal-hot i { transform-origin: center bottom; }
/* The badge tick rides a touch high against the uppercase text — optical centring nudge. */
.wv-avail-badge i { transform: translateY(1px); }
/* Flame shape-dance: three FA flame glyphs stacked, crossfading in turn so the tips move,
   while the whole flame keeps the flicker sway. Falls back gracefully to a single icon. */
.wv-flame { position: relative; display: inline-block; width: 1em; height: 1em; }
.wv-flame i {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: wvFlameShapes 1.3s linear infinite !important;
  opacity: 0;
}
.wv-flame i:nth-child(2) { animation-delay: -0.43s !important; }
.wv-flame i:nth-child(3) { animation-delay: -0.87s !important; }
@keyframes wvFlameShapes {
  0%, 30% { opacity: 1; }
  38%, 92% { opacity: 0; }
  100% { opacity: 1; }
}
.wv-signal-hot .wv-flame { animation: wvFlameFlicker 3.7s linear infinite; transform-origin: center bottom; }
@media (prefers-reduced-motion: reduce) {
  .wv-flame i { animation: none !important; opacity: 0; }
  .wv-flame i:first-child { opacity: 1; }
  .wv-signal-hot .wv-flame { animation: none; }
}
/* Simple flame (the original): one glyph, zoom/bounce flicker. */
@keyframes wvFlameBounce {
  0%, 100% { transform: scale(1) rotate(0deg); opacity: 1; }
  25% { transform: scale(1.12) rotate(-3deg); opacity: 0.85; }
  50% { transform: scale(0.94) rotate(2deg); opacity: 1; }
  75% { transform: scale(1.08) rotate(-2deg); opacity: 0.9; }
}
.wv-signal-hot .wv-flame-simple { animation: wvFlameBounce 1.1s ease-in-out infinite; transform-origin: center bottom; }
@media (prefers-reduced-motion: reduce) {
  .wv-signal-hot .wv-flame-simple { animation: none !important; }
}
/* Tile CTAs pin to the card foot so buttons align across a row despite varying blurb lengths. */
.card-body:has(> .btn.w-100), .card-body:has(> .wv-interest) { display: flex; flex-direction: column; }
.card-body > .btn.w-100 { margin-top: auto !important; }
.card-body > .wv-interest { margin-top: auto; padding-top: 1rem; }
/* Modal two-row header: action on top, subject beneath a step smaller in the body face. */
.modal-title .wv-modal-sub { display: block; font-size: var(--fs-sm); font-family: inherit; letter-spacing: 0.02em; margin-top: 0.15rem; opacity: 0.85; }
/* Scarcity badge coin-spins on its Y axis every few seconds. */
@keyframes wvCoinSpin { 0%, 68% { transform: rotateY(0deg); } 100% { transform: rotateY(360deg); } }
.wv-signal-scarcity i { animation: wvCoinSpin 3.2s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .wv-signal-scarcity i { animation: none; } }
