/* ViveMapa Colección 2026 (24 Sep 2026): the green is now the market's ground.
   Jungle on the region's pages, Azul Talavera in Mexico; set by data-market on
   <html>. The retired gold #C2A24A is Oro #F2B53A everywhere. */
:root{--vm-ground:#1E4D3E;--vm-groundd:#16352B;--vm-ground-rgb:30 77 62;--vm-groundd-rgb:22 53 43}
[data-market="mx"]{--vm-ground:#0B5A3E;--vm-groundd:#083E2A;--vm-ground-rgb:11 90 62;--vm-groundd-rgb:8 62 42}
/* vivemapa.com brand polish on top of Tailwind. Ported from the upstream base's
   core/static/css/brand.css (identity strings only changed). */
html { scroll-behavior: smooth; }
body { -webkit-font-smoothing: antialiased; }
.maplibregl-popup-content { border-radius: 10px; padding: 8px; }
.font-700 { font-weight: 700; }
.font-600 { font-weight: 600; }
.font-500 { font-weight: 500; }
.font-400 { font-weight: 400; }
::selection { background: #C16A43; color: #fff; }
/* truncate helper for 2 lines */
.clamp-2 { display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }

/* rotating hero */
.hero-rotator { position:absolute; inset:0; overflow:hidden; background:var(--vm-groundd); }
.hero-slide { position:absolute; inset:0; background-size:cover; background-position:center;
  opacity:0; animation:heroFade 35s infinite; will-change:opacity; }
.hero-slide:nth-child(1){ animation-delay:0s }
.hero-slide:nth-child(2){ animation-delay:7s }
.hero-slide:nth-child(3){ animation-delay:14s }
.hero-slide:nth-child(4){ animation-delay:21s }
.hero-slide:nth-child(5){ animation-delay:28s }
@keyframes heroFade { 0%{opacity:0} 3%{opacity:1} 17%{opacity:1} 20%{opacity:0} 100%{opacity:0} }
@media (prefers-reduced-motion: reduce){ .hero-slide{ animation:none } .hero-slide:nth-child(1){ opacity:1 } }
.drop-shadow { text-shadow:0 2px 12px rgba(0,0,0,.35); }

/* brand book: the gold line (divider system) */
.rule-gold { height:1px; background:#F2B53A; opacity:.5; border:0; }
.rule-node { display:flex; align-items:center; gap:16px; }
.rule-node::before, .rule-node::after {
  content:""; height:1px; background:#F2B53A; opacity:.5; flex:1; }
.rule-node .nd { width:9px; height:9px; background:#F2B53A;
  border-radius:2px; transform:rotate(45deg); flex:0 0 auto; }
@media (max-width:760px){ .vm-why{ grid-template-columns:1fr !important; } }

/* purged tw build lacks lg:grid-cols-3 (lg-grid3) */
@media (min-width:1024px){ .lg\:grid-cols-3{ grid-template-columns:repeat(3,minmax(0,1fr)); } }

/* ---- mobile overflow hardening ----
   html-level clip: body-level overflow-x-hidden is ignored for scrolling by
   iOS Safari. clip (unlike hidden) creates no scroll container and keeps
   position:sticky working. */
html{overflow-x:clip}
.wrap-any{overflow-wrap:anywhere;word-break:break-word}
.prose img,.prose iframe,.prose video{max-width:100%;height:auto}
.prose table{display:block;max-width:100%;overflow-x:auto}
.prose pre{max-width:100%;overflow-x:auto;white-space:pre-wrap}
.prose a{overflow-wrap:anywhere}
.calc-grid{display:grid;grid-template-columns:1fr;gap:.75rem}
@media (min-width:640px){.calc-grid{grid-template-columns:repeat(3,1fr)}}
.mob-nav-scroll{max-height:calc(100dvh - 4rem);overflow-y:auto}
/* 44px minimum touch target without visual change (Apple HIG / WCAG 2.5.8). */
.tap{position:relative}
.tap::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:max(100%,44px);height:max(100%,44px)}
.tap44{min-width:44px;min-height:44px}

button:disabled, .htmx-request button { opacity: .55; cursor: progress; }

/* --- Utilities MISSING FROM tw.css (see the upstream original for rationale) --- */
.right-3 { right: 0.75rem; }
.top-20 { top: 5rem; }

@media (min-width: 640px) {
  .sm\:left-6 { left: 1.5rem; }
  .sm\:right-6 { right: 1.5rem; }
}

@media (min-width: 1024px) {
  .lg\:top-20 { top: 5rem; }
}


/* ---------------------------------------------------------------------------
   Utilities this site's own markup needs.

   tw.css is a purged Tailwind build inherited with the template: it contains
   only the classes the original markup used. Anything new we write is simply
   absent, which is why two wordmarks rendered at once and why a responsive
   grid silently stayed a single column. There is no Tailwind build step on this
   host, so these are defined here by hand.
   --------------------------------------------------------------------------- */

.vm-wordmark { display: flex; flex-direction: column; line-height: 1;
               font-family: Fraunces, Georgia, serif; font-weight: 700; }

.vm-grid { display: grid; gap: 1.25rem; grid-template-columns: 1fr; }
@media (min-width: 640px)  { .vm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .vm-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.vm-card-img { width: 100%; height: 13rem; object-fit: cover; background: #efe9dc; display: block; }
.vm-clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
              overflow: hidden; }
.vm-hero-title { font-size: 2.25rem; }
@media (min-width: 768px) { .vm-hero-title { font-size: 3rem; } }
.vm-chip { border: 1px solid rgb(var(--vm-ground-rgb) / .25); border-radius: 9999px;
           padding: .35rem 1rem; font-size: .875rem; display: inline-block; }
.vm-chip:hover { background: #efe9dc; }
.vm-field { border: 1px solid rgb(var(--vm-ground-rgb) / .25); border-radius: .375rem;
            padding: .5rem .75rem; color: var(--vm-ground); background: #fff; }
.vm-cta { background: #F2B53A; color: #1C2B25; font-weight: 600;
          padding: .5rem 1.25rem; border-radius: .375rem; border: 0; cursor: pointer; }
.vm-card { border: 1px solid rgb(var(--vm-ground-rgb) / .15); border-radius: .5rem;
           overflow: hidden; background: #fff; }

/* --------------------------------------------------------------------------
   Listing page.

   Written as explicit classes rather than Tailwind utilities on purpose:
   tw.css here is a PURGED build, so arbitrary values and most responsive
   variants simply do not exist in it. h-[380px], lg:col-span-2, lg:sticky,
   sm:grid-cols-3 and line-clamp-2 are all absent, which is why the gallery
   first rendered with a hole in the middle of the thumbnails. Anything this
   page needs, it defines.
   -------------------------------------------------------------------------- */

.vm-gallery { display: grid; gap: .5rem; grid-template-columns: 1fr; }
.vm-gallery-hero { position: relative; display: block; }
.vm-gallery-hero img { width: 100%; height: 300px; object-fit: cover; border-radius: .5rem; display: block; }
.vm-gallery-thumbs { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; }
.vm-gallery-thumb { position: relative; display: block; }
.vm-gallery-thumb img { width: 100%; height: 145px; object-fit: cover; border-radius: .5rem; display: block; }
.vm-photo-count { position: absolute; left: .75rem; bottom: .75rem;
                  background: rgba(20,32,28,.72); color: #F7F3EA;
                  font-size: .75rem; padding: .35rem .6rem; border-radius: .375rem; }
.vm-more-photos { position: absolute; inset: 0; display: grid; place-items: center;
                  background: rgba(20,32,28,.55); color: #F7F3EA;
                  font-weight: 600; border-radius: .5rem; }

@media (min-width: 1024px) {
  /* The hero and the four thumbnails must add up to the SAME height, or the
     grid stretches one of them and leaves the gap this page shipped with. */
  .vm-gallery { grid-template-columns: 2fr 1fr; }
  .vm-gallery-hero img { height: 420px; }
  .vm-gallery-thumb img { height: 206px; }
}

.vm-detail { display: grid; gap: 1.25rem; align-items: start; grid-template-columns: minmax(0, 1fr); }
.vm-stack { min-width: 0; }
@media (min-width: 1024px) {
  .vm-detail { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
  .vm-side { position: sticky; top: 1rem; }
}

.vm-panel { border: 1px solid rgb(var(--vm-ground-rgb) / .15); border-radius: .75rem;
            background: #fff; padding: 1.25rem; }
.vm-stack > * + * { margin-top: 1.25rem; }

.vm-specs { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;
            text-align: center; border-top: 1px solid rgb(var(--vm-ground-rgb) / .12);
            padding-top: 1rem; margin-top: 1.25rem; }
@media (min-width: 640px) { .vm-specs { grid-template-columns: repeat(4, 1fr); } }
.vm-specs dd { font-family: var(--vm-display, Georgia, serif); font-size: 1.25rem; font-weight: 700; }
.vm-specs dt { font-size: .75rem; color: rgb(var(--vm-ground-rgb) / .55); }

.vm-facts { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;
            font-size: .875rem; margin-top: .75rem; }
@media (min-width: 640px) { .vm-facts { grid-template-columns: repeat(3, 1fr); } }

.vm-photo-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; margin-top: .75rem; }
@media (min-width: 640px) { .vm-photo-grid { grid-template-columns: repeat(3, 1fr); } }
.vm-photo-grid img { width: 100%; height: 170px; object-fit: cover; border-radius: .5rem; display: block; }

.vm-nearby { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: .75rem; list-style: none; padding: 0; }
@media (min-width: 1024px) { .vm-nearby { grid-template-columns: repeat(4, 1fr); } }
.vm-nearby img { width: 100%; height: 130px; object-fit: cover; display: block; }
.vm-similar { grid-auto-flow: column; grid-auto-columns: minmax(160px, 72%); grid-template-columns: none; width: 100%; max-width: 100%; overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: .5rem; }
.vm-similar > li { scroll-snap-align: start; }
@media (min-width: 768px) { .vm-similar { grid-auto-flow: row; grid-template-columns: repeat(4, minmax(0, 1fr)); overflow: visible; } }

.vm-map { height: 320px; width: 100%; border-radius: .5rem; margin-top: .75rem; }

.vm-contact-mini { display: flex; gap: .75rem; background: #F2EDE1;
                   border-radius: .5rem; padding: .75rem; margin-top: .75rem; }
.vm-contact-mini img { height: 56px; width: 64px; border-radius: .375rem;
                       object-fit: cover; flex-shrink: 0; }
.vm-btn-row { display: flex; gap: .5rem; }
.vm-btn-row > * { flex: 1 1 0; }
.vm-wa { background: #25D366; color: #fff; font-weight: 600; text-align: center;
         padding: .5rem 1rem; border-radius: .375rem; display: block; }
.vm-pill { border-radius: 9999px; background: #F2EDE1; padding: .25rem .75rem; font-size: .75rem; }
.vm-muted { color: rgb(var(--vm-ground-rgb) / .55); }
.vm-small { font-size: .75rem; }
.vm-trust li { margin-top: .25rem; }

/* --------------------------------------------------------------------------
   Region landing page. Explicit classes again: tw.css is a purged build and
   the responsive grid variants this page needs are not in it.
   -------------------------------------------------------------------------- */

.vm-wrap { max-width: 72rem; margin: 0 auto; padding-left: 1rem; padding-right: 1rem; }
.vm-section { margin-top: 2rem; }
.vm-h2 { font-family: Fraunces, var(--vm-display, Georgia, serif); font-size: 1.25rem;
         font-weight: 700; margin-top: 2.5rem; }
.vm-small { font-size: .8125rem; }
.vm-muted { color: rgb(var(--vm-ground-rgb) / .6); }

.vm-region-hero { background: var(--vm-ground); color: #F7F3EA; padding: 2.5rem 0; }
.vm-region-hero--photo { background-size: cover; background-position: center; }
/* Wikimedia photo credit line, required by the license: taxonomy hero,
   zone-page hero, and one small line per picture card in the zone index. */
.vm-photo-credit { max-width: 80rem; margin: 0 auto; padding: .5rem 1rem; font-size: .75rem; color: rgb(var(--vm-ground-rgb) / .6); }
.vm-photo-credit a { color: inherit; text-decoration: underline; }
.vm-zone-card-credit { margin: .25rem 0 0; font-size: .6875rem; color: rgb(var(--vm-ground-rgb) / .55); }
.vm-zone-card-credit a { color: inherit; text-decoration: underline; }
/* Round 4: same slot as the photo credit, for a generated (no hero_credit)
   banner -- honest labelling, never a photo claim. Italic, no link, so it
   reads visually distinct from a real credit line at a glance. */
.vm-photo-credit--illustrative, .vm-zone-card-credit--illustrative { font-style: italic; }
.vm-region-title { font-size: 1.875rem; font-weight: 700; line-height: 1.15; }
@media (min-width: 768px) { .vm-region-title { font-size: 2.25rem; } }
.vm-region-sub { margin-top: .5rem; max-width: 46rem; color: rgba(247,243,234,.85); }

.vm-deal-toggle { margin-top: 1.25rem; display: inline-flex; gap: .25rem;
                  background: rgba(247,243,234,.15); padding: .25rem; border-radius: 9999px; }
.vm-deal-toggle a { padding: .35rem 1rem; border-radius: 9999px; color: #F7F3EA; font-size: .875rem; }
.vm-deal-toggle a.is-on { background: #F7F3EA; color: var(--vm-ground); font-weight: 600; }
/* A deal or type with no listings: plain text, not a link. */
.vm-deal-toggle span.vm-off { padding: .35rem 1rem; border-radius: 9999px; color: rgba(247,243,234,.55); font-size: .875rem; }
.vm-deal-toggle span.vm-off.is-on { background: #F7F3EA; color: var(--vm-ground); font-weight: 600; opacity: .7; }

/* The quotable sentence. Given its own band so it reads as a statement of
   fact about the place, not as marketing copy inside the hero. */
.vm-capsule { background: #F2EDE1; color: var(--vm-ground); padding: 1rem 0; font-size: .95rem; }

.vm-chips { display: flex; flex-wrap: wrap; gap: .5rem; }
.vm-chips a { border: 1px solid rgb(var(--vm-ground-rgb) / .25); border-radius: 9999px;
              padding: .3rem .85rem; font-size: .875rem; color: var(--vm-ground); }
.vm-chips span.vm-off { border: 1px dashed rgb(var(--vm-ground-rgb) / .2); border-radius: 9999px;
                        padding: .3rem .85rem; font-size: .875rem; color: rgb(var(--vm-ground-rgb) / .5); }

.vm-statrow { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;
              margin-top: 1.5rem; padding: 1rem 0;
              border-top: 1px solid rgb(var(--vm-ground-rgb) / .12);
              border-bottom: 1px solid rgb(var(--vm-ground-rgb) / .12); }
@media (min-width: 768px) { .vm-statrow { grid-template-columns: repeat(4, 1fr); } }
.vm-statrow dt { font-size: .75rem; color: rgb(var(--vm-ground-rgb) / .55); }
.vm-statrow dd { font-family: var(--vm-display, Georgia, serif);
                 font-size: 1.35rem; font-weight: 700; margin: .15rem 0 0; }

.vm-breakdown { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1rem;
                list-style: none; padding: 0; font-size: .8125rem; }
.vm-breakdown li { background: #F2EDE1; border-radius: 9999px; padding: .25rem .75rem; }

.vm-pager { display: flex; gap: 1.25rem; align-items: center;
            justify-content: center; margin-top: 2rem; }

.vm-arealist { display: grid; grid-template-columns: 1fr; gap: .5rem;
               margin-top: .75rem; list-style: none; padding: 0; }
@media (min-width: 640px) { .vm-arealist { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .vm-arealist { grid-template-columns: repeat(3, 1fr); } }
.vm-arealist a { display: block; border: 1px solid rgb(var(--vm-ground-rgb) / .15);
                 border-radius: .5rem; padding: .7rem .9rem; background: #fff; }
.vm-area-name { display: block; font-weight: 600; color: var(--vm-ground); }

/* --------------------------------------------------------------------------
   Homepage. Explicit classes again: tw.css is a purged build.
   -------------------------------------------------------------------------- */

/* Funnel entry cards (home page), 2026-09-26: real photography of the top
   listing in each funnel, replacing the two plain white text boxes Adam
   flagged ("this needs a redesign") -- same dark-gradient-overlay idiom as
   .vm-zone-card (vm-coleccion-live.css) so it reads as one system, just a
   wide single-card layout instead of a tiled thumbnail grid. */
.vm-funnel-cards { display: grid; grid-template-columns: 1fr; gap: 1rem; margin-top: 1rem; }
@media (min-width: 768px) { .vm-funnel-cards { grid-template-columns: repeat(2, 1fr); } }
.vm-funnel-card { position: relative; display: block; aspect-ratio: 16/10;
                  border-radius: .75rem; overflow: hidden;
                  background: var(--vm-groundd); text-decoration: none; }
.vm-funnel-card img, .vm-funnel-card .vm-zone-noimg {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: transform .35s ease; }
.vm-funnel-card:hover img { transform: scale(1.05); }
.vm-funnel-card::after { content: ""; position: absolute; inset: 0;
                         background: linear-gradient(180deg, rgba(0,0,0,0) 35%, rgba(0,0,0,.75) 100%); }
.vm-funnel-card-body { position: absolute; left: 1.1rem; right: 1.1rem;
                       bottom: 1rem; z-index: 1; color: #fff; }
.vm-funnel-card-body b { display: block; font-family: var(--vm-display, Fraunces, Georgia, serif);
                         font-weight: 700; font-size: 1.4rem; line-height: 1.2; }
.vm-funnel-card-count { display: block; font-size: .85rem; color: rgba(255,255,255,.85); margin-top: .2rem; }
.vm-funnel-card-threshold { display: block; font-size: .78rem; color: rgba(255,255,255,.75); margin-top: .15rem; }
.vm-funnel-card-arrow { position: absolute; right: 1rem; top: 1rem; z-index: 1;
                        color: #fff; font-size: 1.4rem; line-height: 1; }
.vm-funnel-card:focus-visible { outline: 3px solid #F2B53A; outline-offset: 2px; }

.vm-home-hero { background-size: cover; background-position: center;
                color: #F7F3EA; }
.vm-home-hero-inner { padding: 3.5rem 1rem 3rem; }
@media (min-width: 768px) { .vm-home-hero-inner { padding: 5rem 1rem 4.5rem; } }
.vm-hero-sub { margin-top: .75rem; max-width: 40rem; font-size: 1.05rem;
               color: rgba(247,243,234,.9); }

.vm-hero-search { margin-top: 1.75rem; max-width: 46rem; }
.vm-deal-toggle--light { background: rgba(247,243,234,.18); }
.vm-deal-toggle--light label { cursor: pointer; }
.vm-deal-toggle--light input { position: absolute; opacity: 0; }
.vm-deal-toggle--light span { display: inline-block; padding: .35rem 1rem;
                              border-radius: 9999px; font-size: .875rem; }
.vm-deal-toggle--light input:checked + span { background: #F7F3EA; color: var(--vm-ground); font-weight: 600; }

.vm-hero-searchrow { margin-top: .75rem; display: grid; gap: .5rem;
                     grid-template-columns: 1fr; }
@media (min-width: 768px) {
  .vm-hero-searchrow { grid-template-columns: 1fr auto auto; }
}
.vm-hero-input, .vm-hero-select { border: 0; border-radius: .5rem;
                                  padding: .75rem 1rem; font-size: 1rem;
                                  color: var(--vm-ground); background: #fff; width: 100%; }
.vm-hero-btn { background: #F2B53A; color: #1C2B25; font-weight: 700;
               border: 0; border-radius: .5rem; padding: .75rem 1.75rem;
               font-size: 1rem; cursor: pointer; }

.vm-hero-stats { margin-top: 1.75rem; display: flex; flex-wrap: wrap;
                 gap: 1.75rem; list-style: none; padding: 0;
                 color: rgba(247,243,234,.85); }
.vm-hero-stats strong { font-family: var(--vm-display, Georgia, serif);
                        font-size: 1.5rem; color: #F2B53A; margin-right: .35rem; }

.vm-linkcols { display: grid; grid-template-columns: 1fr; gap: 2rem;
               margin-top: 1rem; }
@media (min-width: 768px) { .vm-linkcols { grid-template-columns: repeat(3, 1fr); } }
.vm-linkcols ul { list-style: none; padding: 0; margin: .5rem 0 0; }
.vm-linkcols li { margin-top: .35rem; }
.vm-linkcols a { color: #B4533A; }
.vm-linkcols a:hover { text-decoration: underline; }
.vm-colhead { font-weight: 600; color: var(--vm-ground); }

.vm-valueprops { display: grid; grid-template-columns: 1fr; gap: 1.5rem;
                 margin-top: 3rem; padding-top: 2rem;
                 border-top: 1px solid rgb(var(--vm-ground-rgb) / .12); }
@media (min-width: 768px) { .vm-valueprops { grid-template-columns: repeat(3, 1fr); } }
.vm-valueprops h3 { font-family: var(--vm-display, Georgia, serif);
                    font-weight: 700; color: var(--vm-ground); }
.vm-valueprops p { margin-top: .4rem; color: rgb(var(--vm-ground-rgb) / .9); font-size: .925rem; }

/* MapLibre chrome. .vm-map itself is already sized above. */
.vm-map { overflow: hidden; background: #E8E3D8; }
.maplibregl-ctrl-attrib { font-size: 10px; }


/* Facts under the sidebar price. tw.css is a purged build, so the grid is
   spelled out here. */
.vm-pricefacts { margin-top: .75rem; padding-top: .75rem;
                 border-top: 1px solid rgb(var(--vm-ground-rgb) / .12);
                 display: grid; gap: .4rem; }
.vm-pricefacts > div { display: flex; justify-content: space-between;
                       gap: 1rem; font-size: .8125rem; }
.vm-pricefacts dt { color: rgb(var(--vm-ground-rgb) / .55); }
.vm-pricefacts dd { font-weight: 600; margin: 0; }

/* Legal pages. Long prose, so it needs measure and rhythm that the listing
   grid does not. tw.css is a purged build; spelled out here. */
.vm-legal { margin-top: 1.5rem; color: rgb(var(--vm-ground-rgb) / .85); line-height: 1.65; }
.vm-legal h2 { font-family: var(--vm-display, Georgia, serif); font-weight: 700;
               color: var(--vm-ground); font-size: 1.15rem; margin: 2rem 0 .5rem; }
.vm-legal p { margin: .75rem 0; }
.vm-legal ul { margin: .75rem 0 .75rem 1.25rem; list-style: disc; }
.vm-legal li { margin: .3rem 0; }
.vm-legal a { color: #B4533A; text-decoration: underline; }
.vm-legal strong { color: var(--vm-ground); }


/* A listing with one photograph has no thumbnails, so the 2fr/1fr gallery
   grid rendered an empty right-hand column and left a hole beside the hero.
   With nothing to put next to it, the hero takes the whole width. */
.vm-gallery--solo { grid-template-columns: 1fr !important; }
.vm-gallery--solo .vm-gallery-hero img { height: 420px; }
@media (max-width: 767px) {
  .vm-gallery--solo .vm-gallery-hero img { height: 300px; }
}

/* Form controls. tw.css is a purged build, so the inputs were rendering as
   unstyled browser defaults with no border -- the label and the placeholder
   ran together on one line. */
.vm-panel input[type="text"], .vm-panel input[type="email"],
.vm-panel input[type="tel"], .vm-panel input[type="search"],
.vm-panel select, .vm-panel textarea,
main input[type="text"], main input[type="email"],
main input[type="tel"], main select, main textarea {
  display: block; width: 100%; margin-top: .2rem;
  padding: .55rem .7rem; font-size: .9375rem; color: var(--vm-ground);
  background: #fff; border: 1px solid rgb(var(--vm-ground-rgb) / .25);
  border-radius: .45rem; line-height: 1.35;
}
.vm-panel textarea, main textarea { min-height: 5.5rem; resize: vertical; }
.vm-panel input:focus, .vm-panel select:focus, .vm-panel textarea:focus,
main input:focus, main select:focus, main textarea:focus {
  outline: 2px solid rgba(242,181,58,.55); outline-offset: 1px;
  border-color: rgb(var(--vm-ground-rgb) / .45);
}
.vm-panel input[type="checkbox"] { width: auto; display: inline-block;
                                   margin-top: .15rem; }


/* Voice search. The button is created by voice-input.js, so these rules live
   here rather than in tw.css: that build is purged against the templates and
   would drop a class that only ever appears inside a JavaScript string. */
.vm-hero-inputwrap { position: relative; display: block; width: 100%; }
.vm-mic { position: absolute; right: .5rem; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center; width: 2.1rem; height: 2.1rem;
  border: 0; border-radius: 999px; background: transparent; cursor: pointer;
  color: var(--vm-ground); opacity: .65; padding: 0; }
.vm-mic:hover { opacity: 1; background: rgb(var(--vm-ground-rgb) / .08); }
.vm-mic:focus-visible { outline: 2px solid var(--vm-ground); outline-offset: 2px; opacity: 1; }
.vm-mic svg { width: 1.05rem; height: 1.05rem; }
.vm-mic.is-live { opacity: 1; color: #C16A43; background: rgba(193,106,67,.12);
  animation: vm-mic-pulse 1.2s ease-in-out infinite; }
@keyframes vm-mic-pulse { 0%,100% { box-shadow: 0 0 0 0 rgba(193,106,67,.45); }
  50% { box-shadow: 0 0 0 .38rem rgba(193,106,67,0); } }
@media (prefers-reduced-motion: reduce) { .vm-mic.is-live { animation: none; } }
/* Room for the button so a long spoken phrase does not run underneath it. */
.vm-hero-input { padding-right: 2.9rem; }


/* Listing videos and 3D tours (listings/_videos.html). Click to load: the box
   holds a button until pressed, then the embed. 16:9 either way, so the page
   does not jump when the player arrives. */
.vm-video-list { display: grid; gap: .75rem; margin-top: .75rem; }
.vm-video { position: relative; aspect-ratio: 16 / 9; border-radius: .75rem;
  overflow: hidden; background: #0a1b14; }
.vm-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.vm-video-play { position: absolute; inset: 0; width: 100%; border: 0; padding: 0;
  cursor: pointer; background-size: cover; background-position: center;
  display: grid; place-items: center; }
.vm-video-play::before { content: ""; position: absolute; inset: 0;
  background: rgba(10,27,20,.45); transition: background .2s; }
.vm-video-play:hover::before { background: rgba(10,27,20,.3); }
.vm-video-play:focus-visible { outline: 3px solid #F2B53A; outline-offset: -3px; }
.vm-video-badge { position: relative; padding: .65rem 1.1rem; border-radius: 999px;
  background: #F2B53A; color: #1C2B25; font-weight: 700; font-size: .95rem; }

/* The tagline under the logo is wide (tracked capitals) and on a phone it
   pushed the header controls past the right edge: MXN ended at 406px on a
   390px screen, so phone visitors could not switch to pesos at all. */
@media (max-width: 479px) {
  .vm-tagline { display: none; }
}
@media (max-width: 359px) {
  header .tap { padding-left: .3rem; padding-right: .3rem; }
}

/* --------------------------------------------------------------------------
   Zone profile (area page): about/history, ratings, amenities, security,
   growth, planned projects, sources. Same story as every other page here:
   tw.css is a purged Tailwind build and none of this grid/card vocabulary is
   in it, so it is spelled out by hand. Section rendering itself (present +
   has sources) is gated in the view/template, not here.
   -------------------------------------------------------------------------- */

.vm-profile { margin-top: 2.5rem; }
.vm-profile-section { margin-top: 2.5rem; }
.vm-profile-section:first-child { margin-top: 0; }
.vm-profile-h2 { font-family: var(--vm-display, Georgia, serif); font-size: 1.25rem;
                 font-weight: 700; color: var(--vm-ground); margin-bottom: .75rem; }
.vm-profile-prose { color: rgba(28,43,37,.85); line-height: 1.65; }
.vm-profile-prose + .vm-profile-prose { margin-top: 1rem; }

.vm-tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: .75rem; }
@media (min-width: 640px) { .vm-tiles { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .vm-tiles { grid-template-columns: repeat(5, 1fr); } }
.vm-tile { border: 1px solid rgb(var(--vm-ground-rgb) / .15); border-radius: .5rem;
           background: #fff; padding: .85rem; }
.vm-tile-label { font-size: .8125rem; font-weight: 600; color: var(--vm-ground); }
.vm-tile-basis { margin-top: .4rem; font-size: .75rem; color: rgb(var(--vm-ground-rgb) / .6); }

.vm-pips { display: inline-flex; gap: .3rem; margin-top: .5rem; }
.vm-pip { width: .8rem; height: .8rem; border-radius: 2px; transform: rotate(45deg);
          background: rgb(var(--vm-ground-rgb) / .15); display: inline-block; }
.vm-pip--on { background: #F2B53A; }

.vm-disclosure { margin-top: .75rem; font-size: .8125rem; }
.vm-disclosure summary { cursor: pointer; color: var(--vm-ground); font-weight: 600; }
.vm-disclosure p { margin-top: .5rem; color: rgb(var(--vm-ground-rgb) / .7); }

.vm-amenity-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .6rem .75rem;
                    margin-top: .5rem; font-size: .875rem; }
@media (min-width: 640px) { .vm-amenity-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .vm-amenity-grid { grid-template-columns: repeat(4, 1fr); } }
.vm-amenity-grid dt { color: rgb(var(--vm-ground-rgb) / .55); font-size: .75rem; }
.vm-amenity-grid dd { font-weight: 600; color: var(--vm-ground); margin: 0; }

/* Capped at 640px: an SVG's viewBox units become real px 1:1 at that width,
   which is what keeps the label font sizes legible instead of the browser
   stretching a 640-wide coordinate system across an 1100px column and
   blowing a 10px label up to ~18px. Below 640px (phones) the chart still
   just fills its column, same as before. */
.vm-chart-wrap { margin-top: 1rem; max-width: 640px; overflow: hidden; }
.vm-chart { display: block; width: 100%; height: auto; }
.vm-chart-legend { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: .5rem; font-size: .8125rem; }
.vm-chart-legend span { display: inline-flex; align-items: center; gap: .4rem; }
.vm-chart-swatch { width: .7rem; height: .7rem; border-radius: 2px; display: inline-block; }

/* Security: homicidio_doloso and robo_casa are two orders of magnitude
   apart, so they are two small charts on their own scales, not one shared
   axis. Side by side above 640px (each ~310px, same 640px cap as every
   other chart here), stacked full-width on phones. */
.vm-security-charts { display: grid; grid-template-columns: 1fr; gap: 1.25rem;
                       margin-top: 1rem; max-width: 640px; }
@media (min-width: 640px) { .vm-security-charts { grid-template-columns: 1fr 1fr; } }
.vm-security-charts .vm-chart-wrap { margin-top: 0; max-width: none; }
.vm-chart-sublabel { font-size: .8125rem; font-weight: 600; color: var(--vm-ground); margin-bottom: .35rem; }

.vm-stat-row { display: flex; flex-wrap: wrap; gap: 1.5rem; margin-top: .75rem; }
.vm-stat-row .vm-stat { min-width: 8rem; }
.vm-stat dt { font-size: .75rem; color: rgb(var(--vm-ground-rgb) / .55); }
.vm-stat dd { font-family: var(--vm-display, Georgia, serif); font-size: 1.15rem;
              font-weight: 700; color: var(--vm-ground); margin: .1rem 0 0; }

.vm-project-list { list-style: none; padding: 0; margin-top: .75rem; display: grid; gap: .75rem; }
.vm-project { border: 1px solid rgb(var(--vm-ground-rgb) / .15); border-radius: .5rem; padding: .85rem; background: #fff; }
.vm-project-name { font-weight: 600; color: var(--vm-ground); }
.vm-project-meta { font-size: .75rem; color: rgb(var(--vm-ground-rgb) / .55); margin-top: .15rem; }
.vm-project-summary { margin-top: .4rem; font-size: .875rem; color: rgba(28,43,37,.85); }
.vm-project-source { margin-top: .4rem; font-size: .75rem; }
.vm-project-source a { color: #B4533A; text-decoration: underline; }

.vm-source-list { list-style: none; padding: 0; margin-top: .5rem; display: grid; gap: .3rem;
                  font-size: .75rem; color: rgb(var(--vm-ground-rgb) / .6); }
.vm-source-list a { color: #B4533A; text-decoration: underline; }

.vm-note { margin-top: .75rem; font-size: .8125rem; color: rgb(var(--vm-ground-rgb) / .65); }

.vm-tile-grade { font-size: .75rem; font-weight: 600; color: #F2B53A; margin-top: .15rem; }

/* ---- Zone page: child-zone chips under the hero --------------------------
   "pt-8" doesn't exist in the purged tw.css build (see the note at the top
   of this file's listing-page section), so the chips sat with zero space
   under the hero image. Explicit CSS here instead of a Tailwind utility
   class, the same fix pattern as .lg\:grid-cols-3 above. */
.vm-zone-chips-section { margin-top: 1.75rem; }
.vm-chip--zone { background: #F2EDE1; border-color: rgb(var(--vm-ground-rgb) / .2);
                 color: var(--vm-ground); font-weight: 600; padding: .45rem 1.05rem;
                 transition: background .15s ease, border-color .15s ease; }
.vm-chip--zone:hover, .vm-chip--zone:focus-visible {
  background: #F2B53A; border-color: #F2B53A; color: #1C2B25; }

/* ---- Zone page: security comparison table (region/corridor zones) ------- */
.vm-sec-table-wrap { overflow-x: auto; margin-top: .75rem; -webkit-overflow-scrolling: touch; }
.vm-sec-table { width: 100%; border-collapse: collapse; font-size: .8125rem; min-width: 28rem; }
.vm-sec-table th, .vm-sec-table td { text-align: left; padding: .5rem .6rem;
                                      border-bottom: 1px solid rgb(var(--vm-ground-rgb) / .12); }
.vm-sec-table th { font-size: .7rem; text-transform: uppercase; letter-spacing: .03em;
                    color: rgb(var(--vm-ground-rgb) / .55); font-weight: 600; }
.vm-sec-table td:not(:first-child), .vm-sec-table th:not(:first-child) { text-align: right; }
.vm-sec-table-avg { font-weight: 600; color: var(--vm-ground); background: #F7F3EA; }

/* ---- Zone page: map (radius amenities or region/corridor member towns) -- */
.vm-zone-map { margin-top: .75rem; }
.vm-map-legend { display: flex; flex-wrap: wrap; gap: .35rem 1rem; margin-top: .75rem;
                 font-size: .75rem; color: rgb(var(--vm-ground-rgb) / .75); list-style: none; padding: 0; }
.vm-map-legend li { display: flex; align-items: center; gap: .4rem; }
.vm-map-dot { width: .6rem; height: .6rem; border-radius: 9999px; display: inline-block; flex: 0 0 auto; }
.vm-map-dot--school { background: var(--vm-ground); }
.vm-map-dot--hospital { background: #B4533A; }
.vm-map-dot--clinic { background: #C16A43; }
.vm-map-dot--pharmacy { background: #F2B53A; }
.vm-map-dot--supermarket { background: #3B6E8F; }

/* ---- Enquiry form, compact (listing sidebar + dialog) --------------------
   After CRR's phone form: the label sits inside the field's border, so each
   field is one ~46px box instead of a label line over a 40px input. Placed
   last so it wins the ties with the generic ".vm-panel input[type=...]" and
   "main input" rules above (same specificity, later rule). 16px input text:
   smaller makes iOS Safari zoom the page on focus. */
.vm-cf-form > * + * { margin-top: .45rem; }
.vm-cf { display: block; border: 1px solid rgb(var(--vm-ground-rgb) / .25); border-radius: .45rem;
         background: #fff; padding: .28rem .65rem .32rem; }
.vm-cf:focus-within { outline: 2px solid rgba(242,181,58,.55); outline-offset: 1px;
                      border-color: rgb(var(--vm-ground-rgb) / .45); }
.vm-cf > label { display: block; font-size: .6875rem; line-height: .95rem;
                 color: rgb(var(--vm-ground-rgb) / .62); }
.vm-cf input[type="text"], .vm-cf input[type="email"], .vm-cf input[type="tel"],
.vm-cf select, .vm-cf textarea {
  display: block; width: 100%; margin: 0; padding: 0; border: 0; border-radius: 0;
  background: transparent; box-shadow: none; font-size: 16px; line-height: 1.45rem;
  min-height: 1.45rem; color: var(--vm-ground); }
.vm-cf input:focus, .vm-cf select:focus, .vm-cf textarea:focus { outline: none; border: 0; }
.vm-cf textarea { height: 3.1rem; min-height: 3.1rem; resize: vertical; }
.vm-cf ::placeholder { color: rgb(var(--vm-ground-rgb) / .38); }
.vm-cf-consent { display: flex; align-items: flex-start; gap: .5rem; font-size: .75rem;
                 line-height: 1.1rem; color: rgb(var(--vm-ground-rgb) / .75); padding-top: .15rem; }
.vm-cf-consent input { margin-top: .1rem; flex: none; }
.vm-cf-form .vm-cta { width: 100%; padding: .7rem 1rem; }
.vm-cf-note { font-size: .6875rem; line-height: 1rem; color: rgb(var(--vm-ground-rgb) / .5); }

/* The property as a small card above the form: 44px thumbnail, title clamped
   to two lines. */
.vm-contact-mini { align-items: center; padding: .5rem; gap: .6rem; }
.vm-contact-mini img { width: 44px; height: 44px; }
.vm-contact-mini-t { font-size: .8125rem; line-height: 1.05rem; font-weight: 600;
                     display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.vm-contact-mini-p { font-size: .75rem; margin-top: .15rem; color: rgb(var(--vm-ground-rgb) / .62); }

/* Dialog / enquiry page shell. */
.vm-enq { padding: .9rem 1rem 1rem; }
.vm-enq-h { font-family: var(--vm-display, Georgia, serif); font-size: 1.2rem; line-height: 1.5rem;
            font-weight: 700; color: var(--vm-ground); margin: 0 0 .5rem; }
.vm-enq .vm-contact-mini { margin: 0 0 .15rem; }

/* Listing sidebar panel: a little tighter on a phone. */
@media (max-width: 1023px) {
  .vm-lead { padding: 1rem; }
  .vm-lead .vm-contact-mini { margin-top: .5rem; }
}

/* ---- Listing page: phone bottom bar (price + Contactar), after CRR's ----- */
.vm-mbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
           display: flex; align-items: center; gap: .75rem;
           padding: .55rem 1rem calc(.55rem + env(safe-area-inset-bottom));
           background: #FBF8F1; border-top: 1px solid rgb(var(--vm-ground-rgb) / .12);
           box-shadow: 0 -2px 10px rgba(0,0,0,.08); transition: transform .2s ease; }
.vm-mbar.is-off { transform: translateY(115%); }
.vm-mbar-txt { min-width: 0; line-height: 1.15; }
.vm-mbar-price { font-family: var(--vm-display, Georgia, serif); font-weight: 700; font-size: 1rem;
                 color: var(--vm-ground); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vm-mbar-sub { font-size: .6875rem; color: rgb(var(--vm-ground-rgb) / .6);
               white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vm-mbar .vm-cta { margin-left: auto; flex: none; padding: .6rem 1.1rem; font-size: .875rem; border-radius: .5rem; }
@media (min-width: 1024px) { .vm-mbar { display: none; } }
/* The bar replaces the round button on a listing page on a phone. */
@media (max-width: 1023px) { body:has(#vm-mbar) .vm-fab { display: none; } }
@media print { .vm-mbar { display: none; } }

/* ---- Listing page: "Nearby" POI block (worker brief 2026-09-25) ---------
   Own namespace (vm-poi-*), deliberately NOT vm-nearby: that class already
   belongs to the "Propiedades cercanas" listing-card grid above (a 2-up/
   4-up image grid with `.vm-nearby img` rules) -- review round 1 caught
   both blocks sharing one class name, which broke this one's phone layout
   (names/distances clipped off the right edge). Single column under
   640px so a long POI name has the full card width to wrap into instead
   of fighting a 2-up grid for space; 2-up from 640px, 3-up from 1024px. */
.vm-poi { display: grid; grid-template-columns: 1fr; gap: 1.25rem; margin-top: .75rem; }
@media (min-width: 640px) { .vm-poi { grid-template-columns: repeat(2, 1fr); gap: 1.25rem 1.5rem; } }
@media (min-width: 1024px) { .vm-poi { grid-template-columns: repeat(3, 1fr); } }
.vm-poi-group { min-width: 0; }
.vm-poi-h { font-weight: 700; color: var(--vm-ground); font-size: .8125rem;
            margin-bottom: .4rem; }
.vm-poi-list { list-style: none; margin: 0; padding: 0; display: flex;
               flex-direction: column; gap: .5rem; }
/* align-items: flex-start (not baseline/center): once the name wraps to a
   second line, the distance must stay pinned to the first line, not drift
   to the item's vertical middle. */
.vm-poi-item { display: flex; align-items: flex-start; justify-content: space-between;
               gap: .6rem; font-size: .8125rem; line-height: 1.15rem;
               color: rgb(var(--vm-ground-rgb) / .85); }
/* flex: 1 1 auto + min-width: 0 is what lets a long name actually shrink
   and wrap inside a flex row instead of overflowing past the card edge --
   the bug review round 1 screenshotted. No ellipsis/nowrap here on
   purpose: a truncated business name reads as more broken on a phone than
   two short wrapped lines. */
.vm-poi-name { flex: 1 1 auto; min-width: 0; overflow-wrap: break-word; word-break: break-word; }
.vm-poi-dist { flex: 0 0 auto; font-size: .75rem; color: rgb(var(--vm-ground-rgb) / .5);
               white-space: nowrap; padding-top: .05rem; }
.vm-poi-tag { font-size: .6875rem; font-weight: 600; color: #B4533A; }

/* ---- Home: the framed "what we do" plate above the showcase -------------
   Engraved-corner frame (coleccion.css .vm-fr-corner) on the paper mat. */
.vm-explain { --fr-mat: var(--vm-paper, #FFFDF8); padding: 2.6rem 2.4rem 2.1rem;
              margin: 2.25rem 0 .5rem; text-align: center; }
.vm-explain-eyebrow { font-size: .72rem; letter-spacing: .16em; text-transform: uppercase;
                      font-weight: 700; color: var(--vm-accent, #CE1126); }
.vm-explain-h { font-family: Fraunces, var(--vm-display, Georgia), serif; font-weight: 700;
                font-size: clamp(1.35rem, 2.6vw, 2rem); line-height: 1.2; color: var(--vm-ground);
                margin: .5rem auto 0; max-width: 30ch; }
.vm-explain-lede { max-width: 62ch; margin: .7rem auto 0; font-size: 1.02rem; line-height: 1.5;
                   color: rgb(var(--vm-ground-rgb) / .82); }
.vm-explain-rule { max-width: 300px; margin: 1rem auto 1.2rem; }
.vm-explain-points { list-style: none; padding: 0; margin: 0 auto; display: grid; gap: 1.1rem;
                     max-width: 1000px; text-align: left; }
@media (min-width: 768px) { .vm-explain-points { grid-template-columns: repeat(3, 1fr); gap: 1.75rem; } }
.vm-explain-points li { display: flex; flex-direction: column; gap: .3rem; }
.vm-explain-points strong { font-family: Fraunces, var(--vm-display, Georgia), serif; font-size: 1.08rem;
                            font-weight: 700; color: var(--vm-ground); }
.vm-explain-points span { font-size: .9rem; line-height: 1.45; color: rgb(var(--vm-ground-rgb) / .78); }
.vm-explain-close { margin-top: 1.2rem; font-size: .85rem; font-style: italic;
                    color: rgb(var(--vm-ground-rgb) / .65); }
@media (max-width: 640px) {
  .vm-explain { --c: 64px; padding: 3.1rem 1.4rem 2.2rem; }
  .vm-explain-points { text-align: center; }
}

/* ---- Buyer FAQ: taxonomy tiers + zone pages -------------------------------
   Native details/summary, same accordion pattern as .vm-disclosure above but
   its own classes (a full Q&A list, not a single "how we rate" aside). The
   FAQPage JSON-LD in the page <head> is built from the exact same list
   (listings.area_faq), so this markup and the schema text can never drift
   apart -- see that module's own docstring. */
.vm-faq { margin-top: 2.5rem; }
.vm-faq-list { margin-top: .75rem; border-top: 1px solid rgb(var(--vm-ground-rgb) / .12); }
.vm-faq-item { border-bottom: 1px solid rgb(var(--vm-ground-rgb) / .12); }
.vm-faq-q { cursor: pointer; list-style: none; padding: .85rem 0; font-weight: 600;
            color: var(--vm-ground); font-size: .9375rem; }
.vm-faq-q::-webkit-details-marker { display: none; }
.vm-faq-a { margin: 0 0 .85rem; font-size: .875rem; line-height: 1.55;
            color: rgba(28,43,37,.82); }

/* ---- Compare areas (/comparar/): a noindex tool, not a landing page -------
   Picker checkboxes re-submit the same GET form with a new ?zonas= list;
   the result renders one column per selected zone, side by side on desktop
   and stacked on a phone. */
.vm-compare-picker-list { display: flex; flex-wrap: wrap; gap: .5rem 1rem; margin-top: .5rem; }
.vm-compare-picker-item { display: flex; align-items: center; gap: .4rem;
                          font-size: .875rem; color: rgb(var(--vm-ground-rgb) / .8); }
.vm-compare-submit { margin-top: 1rem; padding: .55rem 1.4rem; border-radius: 9999px;
                     background: var(--vm-ground); color: #F7F3EA; font-weight: 600;
                     font-size: .875rem; border: none; cursor: pointer; }
.vm-compare-cols { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
@media (min-width: 768px) { .vm-compare-cols { grid-template-columns: repeat(var(--vm-compare-n, 3), 1fr); } }
.vm-compare-col { border: 1px solid rgb(var(--vm-ground-rgb) / .15); border-radius: .5rem;
                  padding: 1rem; }

/* ---- Currency toggle (base.html) and the listing detail's "precio
   publicado" line (Adam, 2026-09-26: the toggle used to be dead for MXN
   listings). The published-price line stays visible and unconverted even
   after a visitor picks a different currency, so the advertiser's real
   asking price is never more than one line away. */
.vm-published-price { margin-top: .15rem; font-size: .8125rem; color: rgb(var(--vm-ground-rgb) / .6); }
