/*
Theme Name: LVL29 Life Rebuild
Theme URI: https://lvl29life.com/
Author: Team Swifty
Author URI: https://beswifty.com/
Version: 1.0.0
License: GNU General Public License v2 or later
*/

@import url("https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500;600;700&family=Poppins:wght@300;400;500;600;700&display=swap");

/* ============================================================
   SECTION: BASE — START
   ============================================================ */
/* ===== Base ===== */
body {
  font-family: "Poppins", "Segoe UI", Arial, sans-serif;
  color: #4e4e4e;
  background: #ffffff;
}

.font-heading {
  font-family: "Playfair Display", Georgia, serif;
}

.font-subheading {
  font-family: "Poppins", "Segoe UI", Arial, sans-serif;
  font-weight: 300;
  letter-spacing: 3px;
  text-transform: uppercase;
}

/* ============================================================
   SECTION: BASE — END
   ============================================================ */

/* ============================================================
   SECTION: HEADER — START
   ============================================================ */
/* =========================================================
   HEADER
   ========================================================= */

/* --- Squeeze contract (main.js adjustHeaderVisibility) ---
   The JS measures .inner-header against the summed widths of its children and
   hides them one by one — .header-contact, then .header_cta, then .header-menu —
   by adding .hidden. Two things below are load-bearing, not cosmetic:
   1. .hidden must actually hide, or the JS toggles a class that does nothing.
   2. Children must not wrap or shrink, or the measured width never exceeds the
      container and the squeeze never triggers at all. */
.hidden {
  display: none !important;
}

._header .inner-header {
  flex-wrap: nowrap;
}

/* Spacing between header blocks is margin, NOT flex gap, on purpose: the JS
   measures offsetWidth + marginLeft + marginRight and is blind to gap. With gap
   the header overflowed before the squeeze ever thought it was full. */
._header .inner-header > * {
  flex-shrink: 0;
  margin-left: 12px;
  margin-right: 12px;
}

._header .inner-header > *:first-child {
  margin-left: 0;
}

._header .inner-header > *:last-child {
  margin-right: 0;
}

._header ul.main-menu {
  flex-wrap: nowrap;
}

._header ul.main-menu li.menu-item .menu-item-link {
  white-space: nowrap;
}

/* --- Shell --- */
._header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  padding: 18px 0;
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.75) 0%,
    rgba(0, 0, 0, 0) 100%
  );
  transition: all 0.3s ease;
}

/* sticky state — main.js adds .collapsed past 100px of scroll */
._header.collapsed {
  padding: 10px 0;
  background: #382f2d;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
}

._header .inner-header {
  align-items: center;
  justify-content: space-between;
  min-height: 70px;
}

/* --- Logo --- */
._header .logo-wrapper {
  display: flex;
  align-items: center;
}

._header .logo-wrapper a.logo {
  display: inline-flex;
  align-items: center;
  line-height: 1;
}

._header .logo-wrapper a.logo img {
  height: 56px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  object-position: left center;
  transition: all 0.3s ease;
}

._header .logo-wrapper a.sticky-logo {
  display: none;
}

._header.collapsed .logo-wrapper a.main-logo {
  display: none;
}

._header.collapsed .logo-wrapper a.sticky-logo {
  display: inline-flex;
}

._header.collapsed .logo-wrapper a.logo img {
  height: 44px;
}

/* --- Main menu --- */
._header ul.main-menu {
  display: flex;
  align-items: center;
  gap: 4px;
}

._header ul.main-menu li.menu-item .menu-item-link {
  display: block;
  padding: 10px 12px;
  transition: color 0.3s ease;
}

/* --- Phone block --- */
._header .phone-wrap {
  display: flex;
  align-items: center;
  gap: 10px;
}

._header .calling-icon {
  display: flex;
  align-items: center;
  font-size: 1.25rem;
}

._header .contact-heading {
  display: block;
  text-transform: capitalize;
  line-height: 1.2;
}

._header .contact-number {
  margin: 0;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

._header .divider {
  padding-left: 21px;
  opacity: 0.5;
}

._header .header-contact {
  display: flex;
  align-items: center;
}

/* --- CTA buttons --- */
._header .header-cta {
  display: flex;
  align-items: center;
  gap: 12px;
}

._header .header-btn {
  padding: 10px 22px;
  white-space: nowrap;
}

/* --- Burger — always visible, last item on the right --- */
._header .hamburger-menu {
  display: flex;
  align-items: center;
}

._header .menu_trigger {
  position: relative;
  width: 35px;
  height: 24px;
  cursor: pointer;
}

/* bars take their colour from the text-color-* classes in the markup */
._header .menu_trigger span {
  position: absolute;
  right: 0;
  display: block;
  height: 3px;
  background-color: currentColor;
  transition: all 0.3s ease;
}

._header .menu_trigger span:nth-child(1) {
  top: 0;
  width: 35px;
}

._header .menu_trigger span:nth-child(2) {
  top: 50%;
  width: 25px;
  transform: translateY(-50%);
}

._header .menu_trigger span:nth-child(3) {
  bottom: 0;
  width: 35px;
}

._header .menu_trigger:hover span {
  width: 35px;
}

/* open state — main.js adds .menu_active */
._header .menu_trigger.menu_active span:nth-child(1) {
  top: 50%;
  width: 35px;
  transform: translateY(-50%) rotate(45deg);
}

._header .menu_trigger.menu_active span:nth-child(2) {
  opacity: 0;
}

._header .menu_trigger.menu_active span:nth-child(3) {
  bottom: auto;
  top: 50%;
  width: 35px;
  transform: translateY(-50%) rotate(-45deg);
}

/* ============================================================
   SECTION: HEADER — END
   ============================================================ */

/* ============================================================
   SECTION: MOBILE MENU PANEL — START
   ============================================================ */
/* =========================================================
   MOBILE MENU PANEL
   Layout, colours and responsive behaviour all come from
   assets/css/component-common.css — do not restate them here.
   Only the few hooks that file does not define live below.
   ========================================================= */

/* .bg-white is on the panel in the markup but is defined in neither
   component-common.css nor dynamic-styles.css (which has .bg-light). */
.mobile-menu-wrap.bg-white {
  background-color: #ffffff;
}

/* Submenus stay open by default (no accordion, no trigger arrow), which is
   also component-common.css's own default — its rule to hide a closed submenu
   is commented out there. Nothing to add here.

.mobile-menu-wrap ul.main-menu ul.sub-menu {
  display: none;
}
*/

/* component-common.css has no rule for the divider between the contact
   block and the CTA buttons. */
.menu-devider {
  height: 1px;
  margin: 25px 0;
  background: rgba(80, 44, 30, 0.2);
}


/* ============================================================
   SECTION: MOBILE MENU PANEL — END
   ============================================================ */

/* ============================================================
   SECTION: HERO BANNER (IMAGE SLIDER) — START
   ============================================================ */
/* ===== HERO BANNER (image slider) ===== */
.hero-banner {
  position: relative;
  overflow: hidden;
  background: #000000;
}

.hero-container {
  position: relative;
}

/* the slider is hidden until slick initialises so un-styled slides never flash */
.hero-slider {
  height: 100vh;
  min-height: 560px;
  visibility: hidden;
}

.hero-slider.slick-initialized {
  visibility: visible;
}

.hero-slider .slick-list,
.hero-slider .slick-track {
  height: 100%;
}

.hero-slider .slick-slide {
  height: 100vh;
  min-height: 560px;
}

.slide-outer {
  position: relative;
  height: 100%;
  overflow: hidden;
}

/* image wrappers — never a CSS background-image */
.slide-bg {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.slide-bg img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}

.slide-bg.mob-bg {
  display: none;
}

/* overlay is a real div — backend sets its colour inline */
.slide-overlay {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

/* caption sits low in the frame, centred, like the live site */
.slide-flex-wrapper {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 5;
  display: flex;
  flex-flow: column;
  justify-content: flex-end;
  padding-bottom: 130px;
}

.slide-content-box {
  text-align: center;
}

/* per-slide entrance — driven by slick's active class, no AOS */
.slide-content {
  opacity: 0;
  transform: translateY(35px);
  transition:
    opacity 0.8s ease 0.5s,
    transform 0.8s ease 0.5s;
}

.slick-slide.slick-active .slide-content {
  opacity: 1;
  transform: translateY(0);
}

.hero-banner .hero-content p {
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}

.hero-banner .section-buttons {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 25px;
}

.hero-banner .btn {
  min-width: 190px;
}

/* ============================================================
   SECTION: HERO BANNER (IMAGE SLIDER) — END
   ============================================================ */

/* ============================================================
   SECTION: HERO BANNER (VIDEO BACKGROUND) — START
   ============================================================ */
/* =========================================================
   HERO BANNER — VIDEO BACKGROUND
   Same shell as the slider hero: full-bleed 100vh, real <div> overlay whose
   colour the backend sets inline, caption low and centred. The embed is
   oversized and centred so it fills the frame edge-to-edge at any aspect
   ratio (an iframe cannot object-fit), and it is dropped entirely below 767
   in favour of the .mob-bg still.
   ========================================================= */
.hero-banner.video-banner .video-wrapper {
  position: relative;
  height: 100vh;
  min-height: 560px;
  overflow: hidden;
}

/* poster + mobile still share the same box */
.hero-banner.video-banner .vimeo-thumbnail,
.hero-banner.video-banner .slide-bg {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.hero-banner.video-banner .vimeo-thumbnail img,
.hero-banner.video-banner .slide-bg img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}

.hero-banner.video-banner .slide-bg.mob-bg {
  display: none;
}

/* the embed sits above the poster once it paints */
.hero-banner.video-banner .video-iframe-wrapp {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 2;
}

/* Full-bleed cover for a 16:9 embed. An iframe cannot object-fit, so the box is
   sized to the viewport on one axis and to the 16:9 partner value on the other,
   with min-* forcing whichever axis would come up short — the result always
   covers, never letterboxes, and never over-zooms the way a flat 200% does.
   56.25vw = 9/16 of the width, 177.78vh = 16/9 of the height. */
.hero-banner.video-banner .video-iframe-wrapp iframe,
.hero-banner.video-banner .wistia_responsive_wrapper iframe {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100vw;
  height: 56.25vw;
  min-width: 177.78vh;
  min-height: 100vh;
  transform: translate(-50%, -50%);
  border: 0;
  pointer-events: none;
}

.hero-banner.video-banner .slide-overlay {
  z-index: 3;
}

.hero-banner.video-banner .video-container {
  position: absolute;
  bottom: 130px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
}

.hero-banner.video-banner .video-content {
  text-align: center;
}

/* ============================================================
   SECTION: HERO BANNER (VIDEO BACKGROUND) — END
   ============================================================ */

/* ============================================================
   SECTION: HOME GALLERY — START
   ============================================================ */
/* =========================================================
   HOME GALLERY
   v1 look: full-bleed 3-up carousel, no gaps between slides, uniform 500px
   image height, and a joined bronze arrow block sitting bottom-centre over
   the images. The heading block stays inside the container above it.
   ========================================================= */
.home-gallery {
   contain: paint;
}

/* The carousel runs edge-to-edge like v1, so this section's .container is
   released to full width and only the heading block is constrained. Done this
   way rather than a 100vw breakout because 100vw includes the scrollbar —
   that left the band 7px off-centre and short on the right. */
.home-gallery .container {
  max-width: 100%;
  padding-left: 0;
  padding-right: 0;
}

.home-gallery .gallery-content {
  max-width: 960px;
  margin: 45px auto 45px;
  padding: 0 16px;
  text-align: center;
}

.home-gallery .image-carousel {
  position: relative;
  text-align: center;
}

.home-gallery .home-gallery-carousel {
  position: relative;
}

/* no gaps — slides butt straight up against each other */
.home-gallery .magnific-img {
  padding: 0;
}

.home-gallery .magnific-img a {
  display: block;
  line-height: 0;
}

.home-gallery .magnific-img img {
  width: 100%;
  height: 500px;
  object-fit: cover;
  object-position: center center;
}

/* --- Arrow block, bottom-centre (ported from live-html-css-lvl29) ---
   slick appends both buttons into .gallery-arrows, so they sit as one joined
   block. Colours come from the bg-secondary-transparent / bg-secondary-hover /
   text-color-light classes on the buttons, so the backend can retheme them. */
/* Pulled up over the foot of the images with a negative margin rather than
   absolute + bottom:0 — .image-carousel also wraps the Explore link, so
   bottom:0 anchored the block below the whole thing instead of on the photos.
   The negative margin cancels its own height, so the link keeps its spacing. */
.home-gallery .gallery-arrows {
  position: relative;
  z-index: 10;
  display: flex;
  width: fit-content;
  margin: -72px auto 0;
}

.home-gallery .gallery-arrows .slick-prev-arrow,
.home-gallery .gallery-arrows .slick-next-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 90px;
  height: 72px;
  padding: 0;
  border: 0;
  border-radius: 0;
  font-size: 1.6rem;
  cursor: pointer;
  transition: all 0.3s ease;
}

/* --- Explore Gallery link --- */
.home-gallery .explore-text {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 35px;
  font-weight: 500;
  letter-spacing: 1px;
  text-transform: uppercase;
  transition: all 0.3s ease;
}

.home-gallery .explore-text:hover {
  color: #9f662d;
}

.home-gallery .explore-text .chevron-typ2 {
  display: none;
}

.home-gallery .explore-text:hover .chevron-typ1 {
  display: none;
}

.home-gallery .explore-text:hover .chevron-typ2 {
  display: inline-block;
}

/* ============================================================
   SECTION: HOME GALLERY — END
   ============================================================ */

/* ============================================================
   SECTION: ADDITIONAL CONTENT 3 — START
   Ported from live-html-css-lvl29. Beige rounded box that overhangs
   the section below it, photo background behind, copy left and the
   two counters right. v1's var(--*) tokens are written out as literal
   values here because this theme deliberately has no :root block.
   ============================================================ */
.additional-content-3 {
  position: relative;
  background-color: #000000;
}

.additional-content-3 .section-bg-wrap {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  overflow: hidden;
}

.additional-content-3 .section-bg-img {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}

/* Overlay div — brown tint over the photo, colour set by the
   bg-dark-transparent class in the markup so the backend can retheme it. */
.additional-content-3 .section-bg-overlay {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.container.container-medium {
  max-width: 1140px;
  display: flex;
}

.additional-content-3 .container {
  position: relative;
  z-index: 5; /* box floats above whatever section it hangs into */
  margin-bottom: -130px; /* box overhangs its section */
  background: rgba(163, 147, 131, 0.7);
  padding: 50px 100px 85px;
  text-align: right;
  border-bottom-left-radius: 300px;
}

.additional-content-3 .section-details,
.additional-content-3 .section-counters {
  position: relative;
  width: 50%;
}

/* serif, matching live — the description reads as a heading there */
.additional-content-3 .section-details .section-content p {
  margin: 0;
  font-family: "Playfair Display", Georgia, serif;
  font-size: 2rem;
  font-weight: 600;
  line-height: 1.4;
}

.additional-content-3 .single-counter-item {
  display: block;
  max-width: 320px;
  margin: 0 auto;
  padding: 30px 20px;
  text-align: center;
  border-bottom: 1px solid #9f662d;
  transition: all 0.8s ease;
}

.additional-content-3 .single-counter-item span.counter-detail {
  display: block;
  margin: 0;
  font-size: 1.071rem;
  font-weight: 700;
  line-height: 1.5;
  color: #382f2d;
}

.additional-content-3 .single-counter-item span.counter-number {
  display: block;
  font-family: "Playfair Display", Georgia, serif;
  font-size: 3.429rem;
  font-weight: 700;
  line-height: 1.2;
}
/* ============================================================
   SECTION: ADDITIONAL CONTENT 3 — END
   ============================================================ */

/* ============================================================
   SECTION: APPLY NOW BUTTON — START
   The floating application CTA, ported from live-html-css-lvl29
   (a.apply-link, live style.css:1186-1245). v1 ships it on every page and so
   does this theme — all 12.

   Nothing in component-common.css touches .apply-link; the component system
   has no floating-CTA of its own, so this is the whole of its styling.

   Colour is NOT set here. The markup carries bg-secondary-transparent
   (rgba(185,102,45,.85), dynamic-styles.css:45) and text-color-light, so the
   backend can re-theme the button — v1 hardcodes the same look as
   rgba(159,102,45,.9). The only hardcoded colour below is the ring, because a
   ::after pseudo-element cannot take a dynamic class.

   Position note: `top: 105px` clears the fixed header, which is why the button
   is anchored to the viewport rather than to the page.
   ============================================================ */
a.apply-link {
  position: fixed;
  top: 105px;
  right: 35px;
  z-index: 99;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 115px;
  height: 115px;
  border-radius: 50%;
  font-size: 0.833rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.3;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  transition: all 0.3s ease;
}

/* the thin ring sits 5px outside the disc */
a.apply-link::after {
  content: "";
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  width: calc(100% + 10px);
  height: calc(100% + 10px);
  transform: translate(-50%, -50%);
  border: 1px solid currentColor;
  border-radius: 50%;
}

a.apply-link:hover {
  transform: scale(1.04);
}

/* ----- homepage variant (live-html-css-lvl29 a.circle-cta, style.css:1205) -----
   index.html only. Same disc, moved to the top LEFT, and the ring becomes a
   single arc: ::after keeps only its left border and is rotated -45deg, so what
   shows is a quarter-circle sweeping the top-left of the button rather than a
   closed ring.

   Two classes plus the element (0,2,1) out-rank the base rule (0,1,1), so the
   left/right swap survives the responsive steps below without repeating. */
a.apply-link.circle-cta {
  top: 95px;
  right: auto;
  left: 20px;
}

a.apply-link.circle-cta::after {
  border: 0;
  border-left: 1px solid currentColor;
  transform: translate(-50%, -50%) rotate(-45deg);
}
/* ============================================================
   SECTION: APPLY NOW BUTTON — END
   ============================================================ */

/* ============================================================
   SECTION: FOOTER CTA — START
   v1's design: the photo fills the whole section behind a dark gradient,
   with the copy centred over it. This markup has the photo in .right-col,
   so that column is lifted out of the flex flow and pinned across the
   section as the background, and .left-col spans the full width on top.
   The gradient is a ::after on .right-col because this markup has no
   overlay div — add one if the backend needs to colour it.
   ============================================================ */
/* clip-path is what makes the parallax work: it turns this section into the
   containing block for its position:fixed child AND clips it to the section
   bounds. v1 gets the same effect with background-attachment:fixed, but that
   only applies to CSS backgrounds and this photo is a real <img>. */
.footer-cta {
  position: relative;
  padding: 295px 0 125px; /* top room — the beige box hangs 130px into this section */
  overflow: hidden;
  clip-path: inset(0);
  background-color: #000000;
}

/* --- Right column becomes the full-bleed parallax background ---
   Fixed to the viewport, clipped to the section by the rule above, so the
   photo holds still while the section scrolls over it. */
.footer-cta .right-col {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  z-index: 0;
}

.footer-cta .footer-cta-image {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  line-height: 0;
}

/* max-height:none overrides component-common.css's `.footer-cta-image img
   { max-height: 650px }`, which capped the photo and left a strip of the
   section uncovered at wide viewports. */
.footer-cta .footer-cta-image img {
  width: 100%;
  height: 100%;
  max-height: none;
  object-fit: cover;
  object-position: center center;
}

/* dark gradient over the photo, matching v1 */
.footer-cta .right-col::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: linear-gradient(90deg, rgba(56, 47, 45, 0.5) 0, #000 80%);
}

/* --- Copy sits centred on top ---
   The wrapper must NOT be positioned: it carries .container, which
   component-main.css sets to position:relative, and that made it the offset
   parent for .right-col — pinning the photo to the 1140px container instead
   of to the section. Forced static here; the stacking context moves to
   .left-col instead. */
.footer-cta .footer-cta-wrapper {
  position: static;
  max-width: 1140px;
}

.footer-cta .left-col {
  position: relative;
  z-index: 2;
  width: 100%;
  text-align: center;
}

.footer-cta .footer-cta-content .section-title {
  margin-left: auto;
  margin-right: auto;
}
.footer-cta .footer-cta-content h3{
  margin-left: auto;
  margin-right: auto;
}
.footer-cta .footer-cta-content .section-content {
  margin: 0 auto 30px;
  padding: 25px 0;
  border-top: 1px solid #9f662d;
  border-bottom: 1px solid #9f662d;
}

.footer-cta .footer-cta-content .cta-text {
  font-weight: 300;
}

.footer-cta .footer-cta-content a:not(.btn) {
  color: #b98a52;
  text-decoration: underline;
}

/* --- Button: uppercase, letterspaced, with v1's ring --- */
.footer-cta .cta-buttons {
  display: flex;
  justify-content: center;
  margin-top: 50px;
  padding-top: 25px;
}

.footer-cta .cta-buttons > a {
  position: relative;
  margin: 50px 0;
  text-transform: uppercase;
  letter-spacing: 1px;
}

/* circle ring decoration around the button, like live site */
.footer-cta .cta-buttons > a::after {
  content: "";
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 130px;
  height: 130px;
  background: url("../images/icons/half-circle.svg") no-repeat 50%;
  opacity: 0.9;
  pointer-events: none;
}
/* ============================================================
   SECTION: FOOTER CTA — END
   ============================================================ */

/* ============================================================
   SECTION: HOME MAP — START
   Ported from live-html-css-lvl29's #neighborhood (.google-map-wrapper),
   mapped onto this markup's .home-map / .map-wrapper. Translucent white
   box with a large top-right radius, riding 100px up over the footer CTA
   above it, on a dark brown ground. Map 65% / copy 35%, address row below.
   ============================================================ */
.home-map {
  position: relative;
  background: #382f2d;
  padding-bottom: 100px;
}

/* the white box rides up over the footer CTA */
.home-map .container {
  position: relative;
  z-index: 2;
  display: flex;
  flex-flow: wrap;
  padding: 50px 0;
  background: rgba(255, 255, 255, 0.75);
  border-radius: 0 200px 0 0;
  transform: translateY(-100px);
  overflow: hidden;
}

.home-map .map-section-header {
  width: 100%;
  padding: 0 50px;
}

.home-map .section-title {
  color: #382f2d;
}

/* --- Map: shares the row with the copy column --- */
.home-map .map-wrapper {
  width: 65%;
  min-height: 450px;
}

.home-map .map-wrapper iframe {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 450px;
  border: 0;
}

/* --- Copy + CTA --- */
.home-map .global-map-content {
  width: 35%;
  padding: 0 45px;
}

/* .section-content p sizing is owned by typography/typo.css — nothing here. */

.home-map .global-map-content .btn {
  width: 100%;
  max-width: 300px;
  margin: 20px 0;
  padding: 20px 35px;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 1px;
}

/* --- Address / phone row --- */
.home-map .map-contact {
  width: 100%;
  padding: 50px 50px 0;
}

.home-map .map-contact h3 {
  font-family: "Poppins", "Segoe UI", Arial, sans-serif;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: #382f2d;
}

.home-map .map-contact .address {
  display: inline-block;
  vertical-align: top;
  width: 25%;
  padding-right: 50px;
  border-right: 1px solid;
}

.home-map .map-contact .contact {
  display: inline-block;
  vertical-align: top;
  width: 25%;
  padding-left: 50px;
}

.home-map .map-contact .address span,
.home-map .map-contact .contact a {
  display: block;
  font-family: "Playfair Display", Georgia, serif;
  font-weight: 700;
  font-size: 1.929rem;
  line-height: 1.2;
}
/* ============================================================
   SECTION: HOME MAP — END
   ============================================================ */

/* ============================================================
   SECTION: INNER HERO BANNER — START
   swifty_component_inner_hero_section() — used by amenities.html.

   The MARKUP is the Swifty component so the backend can generate it, but the
   DESIGN is the one this theme already had: the photo is a full-bleed backdrop
   anchored to the top of .inner-page-body-wrapper, running behind the intro and
   fading to black — NOT a self-contained banner band with a title plate.

   That means the section is taken out of the flow (position: absolute) so the
   intro sits over it, exactly as the old .page-hero-bg div did. The gradients
   below are the same two the .page-hero-bg block uses further down; keep them
   in step if either is ever changed.

   component-common.css supplies only the ≤767px swap between .desktop-bg and
   .mob-bg (lines 3739 / 3746). Everything else is missing from the framework
   and is written here.
   ============================================================ */
.inner-page-body-wrapper .inner-hero-section {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  /* a fixed 56vw band anchored to the top of the wrapper — it does not belong
     to the intro and does not shrink with the copy */
  height: 56vw;
  overflow: hidden;
}

.inner-hero-section .inner-hero-container {
  height: 100%;
  padding: 0;
}

.inner-hero-section .inner-hero-img,
.inner-hero-section .image-wrap {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.inner-hero-section .inner-hero-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

/* The framework only sets .mob-bg { display: block } INSIDE its 767 block
   (component-common.css:3746) — nothing hides it above that. Without this base
   rule both banners stack on desktop. */
.inner-hero-section .mob-bg {
  display: none;
}

/* The component ships an <h1> title plate. This design has no title over the
   photo — the page title is the intro's own heading below — so the block is
   hidden rather than removed, keeping the backend markup contract intact. */
.inner-page-body-wrapper .inner-hero-section .inner-hero-content {
  display: none;
}

/* bottom fade over the lower 60% only, so the top of the photo stays clean */
.inner-page-body-wrapper .inner-hero-section::before {
  content: "";
  display: block;
  position: absolute;
  z-index: 1;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 60%;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 25%, #000000 80%);
}

/* large radial vignette; this is what makes the photo read as emerging from
   black. A plain linear fade alone looks flat. */
.inner-page-body-wrapper .inner-hero-section::after {
  content: "";
  display: block;
  position: absolute;
  z-index: 1;
  top: calc(50% - 225px);
  left: 50%;
  width: 120%;
  height: 100vw;
  border-radius: 50%;
  background: radial-gradient(
    ellipse at center,
    #000000 0,
    rgba(0, 0, 0, 0.25) 100%
  );
  transform: translate(-50%, -50%);
  opacity: 0.85;
}
/* ============================================================
   SECTION: INNER HERO BANNER — END
   ============================================================ */

/* ============================================================
   SECTION: NEIGHBORHOOD HERO + INTRO — START
   Ported from live-html-css-lvl29's neighborhood page. Same two components as
   amenities (.inner-hero-section + .intro-type-1) but a different treatment,
   so everything here is scoped under .page-nb on the wrapper — without that
   scope these rules would rewrite the amenities hero too.

   Two differences from amenities: the photo runs the FULL height of the wrapper
   behind a left-to-right gradient (amenities fades to black at the bottom with
   a radial vignette), and the intro copy sits in a right-hand column instead of
   centred.
   ============================================================ */

/* v1: .page-hero-bg.page-nb { height: 100% } — the photo covers the whole
   wrapper, not amenities' fixed 56vw band */
.inner-page-body-wrapper.page-nb .inner-hero-section {
  height: 100%;
}

/* v1: .page-hero-bg.page-nb::before — dots motif down the right side */
.inner-page-body-wrapper.page-nb .inner-hero-section::before {
  top: 115px;
  right: 8.984375vw;
  bottom: auto;
  left: auto;
  width: 100px;
  height: 100%;
  max-height: 750px;
  background: url(../images/icons/pattern-dots.svg) no-repeat 50%;
  opacity: 1;
  z-index: 2;
}

/* v1: .page-hero-bg.page-nb::after — flat left-to-right darkening, replacing
   the radial vignette the amenities hero uses */
.inner-page-body-wrapper.page-nb .inner-hero-section::after {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 0;
  transform: none;
  opacity: 1;
  background: linear-gradient(90deg, rgba(0, 0, 0, 0.5) 26%, #000000);
}

/* v1: .inner-page-intro.to-right — copy pushed into a right-hand column, over
   the photo. Overrides .intro-type-1's centred 665px .content-wrapper.

   The column is a fixed width pushed right with margin-left:auto, NOT v1's
   "wide box with a big left padding". Two reasons that approach failed here:
   v1's fixed 800px inset left only ~280px of text on a wide screen, so
   headings broke mid-phrase; and swapping it for a percentage does not help,
   because percentage padding resolves against the PARENT's width, not the
   element's — 52% became a 740px inset and the column was still only 340px.
   A fixed max-width gives the same readable column at every desktop size. */
.page-nb .intro-type-1.intro-to-right .content-wrapper {
  width: 100%;
  /* 440 box = 400px of text. Narrower than the 560 it started at, and chosen
     so the centred FIND US AT cue clears it: with the column pinned right the
     clearance works out to containerWidth/2 - boxWidth - 83, which is
     independent of the viewport and depends only on the container max at each
     breakpoint. At 440 that stays positive down to the 1024 breakpoint
     (+209px at the widest container, +47px at the narrowest above 1024);
     at 560 it went negative below ~1440 and the cue ran into the copy. */
  max-width: 440px;
  margin-left: auto;
  margin-right: 0;
  padding: 240px 20px 90px;
  text-align: left;
}

/* v1 downsizes the neighborhood title (typography.css:118 — 30px). Expressed in
   rem so it keeps tracking typo.css's stepped root font-size. */
.page-nb .intro-type-1.intro-to-right .intro-heading .section-title {
  margin: 0 0 20px;
  font-size: 2.143rem;
}

/* --- FIND US AT: rotated, bouncing scroll cue ---
   Centred, matching v1. The copy column is a fixed 520px pinned right, so the
   cue clears it on a wide screen; the narrower breakpoints pull it further
   left (see the 1024 block) because the column's left edge marches left as the
   container shrinks. */
.page-nb .location-content__cta {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 9;
  transform: translate(-50%, -50%);
  /* own compositing layer — stops the rotated text jittering during the hop */
  will-change: transform;
  animation: bounce 7s infinite alternate;
}

.page-nb .location-content__cta a {
  display: flex;
  align-items: center;
  font-size: 0.667rem;
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: 0.2em;
  transform: rotate(-90deg);
}

.page-nb .location-content__cta span {
  position: relative;
  display: block;
  width: 57px;
  height: 57px;
  margin-right: 20px;
}

.page-nb .location-content__cta span::before,
.page-nb .location-content__cta span::after {
  content: "";
  display: block;
  position: absolute;
  border-radius: 50%;
  background-color: rgba(214, 209, 196, 0.12);
}

.page-nb .location-content__cta span::before {
  top: 0;
  left: 0;
  width: 57px;
  height: 57px;
}

.page-nb .location-content__cta span::after {
  top: 12.5px;
  left: 12.5px;
  width: 32px;
  height: 32px;
}

.page-nb .location-content__cta span svg {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 14px;
  transform: translate(-50%, -50%);
}

/* rest, hop up at the midpoint, rest again. The translateX(-50%) has to be
   repeated in every frame or the element snaps back to the left on animate. */
@keyframes bounce {
  0%,
  30%,
  70%,
  100% {
    transform: translateY(0) translateX(-50%);
  }
  50% {
    transform: translateY(-50px) translateX(-50%);
  }
}
/* ============================================================
   SECTION: NEIGHBORHOOD HERO + INTRO — END
   ============================================================ */

/* ============================================================
   SECTION: NEIGHBORHOOD MAP + PLACES — START
   The markup is Swifty's Variant B, which the framework styles as a TWO-PANE
   layout: map on the left, a vertical bulleted list on the right, capped at
   549px and scrolling down. v1's design is stacked instead — a full-width map
   with a horizontal scrolling strip of places beneath it — so the rules below
   turn the component's own layout back off.

   Every override is written .neighborhood.new-section, matching the shape
   component-common.css uses (component-common.css:2424-2553). style.css loads
   last, so equal specificity resolves here. Written any weaker and the
   framework's column layout silently wins.

   Untouched framework behaviour, deliberately reused rather than rewritten:
   .nbp-filter-mob-wrap is hidden by default and revealed at ≤767, where
   .nbp-filter-opt-wrapp is killed with !important (component-common.css:4049
   and :4053). That is exactly v1's pills-to-dropdown swap, so it is left alone.
   ============================================================ */

/* --- Filter pill rail --- */
.neighborhood.new-section .nbp-filter-wrapper {
  padding: 20px 0;
}

.neighborhood.new-section .nbp-filter-opt-wrapp {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

/* the rail scrolls horizontally; main.js drives the arrows either side */
.neighborhood.new-section .nbp-filter-scroll {
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.neighborhood.new-section .nbp-filter-scroll::-webkit-scrollbar {
  display: none;
}

.neighborhood.new-section .nbp-filter-options {
  display: flex;
  gap: 4px;
  width: max-content;
  margin: 0 auto;
}

/* v1: div#nbp-filter-options a.nb-map-filter — the rounded outline pill. The
   hover/active fill comes from the bg-primary-* and text-color-light-* classes
   on the markup, so no colour is named here. */
.neighborhood.new-section .nb-map-filter {
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 6px 16px;
  border: 1px solid rgba(163, 147, 131, 1);
  border-radius: 50px;
  white-space: nowrap;
  font-size: 0.722rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  cursor: pointer;
  transition: all 0.2s;
}

.neighborhood.new-section .nb-map-filter i.swi {
  margin-right: 6px;
  font-size: 1em;
}

/* main.js adds .hidden to an arrow when the rail is at that end */
.neighborhood.new-section .nbp-nav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}

.neighborhood.new-section .nbp-nav-btn.hidden {
  visibility: hidden;
}

/* --- Stacked layout: map above, places below (v1), not side by side --- */
.neighborhood.new-section .map-list-wrapper {
  display: block;
}

.neighborhood.new-section .map-canvas {
  width: 100%;
  height: 50vh;
  min-height: 450px;
}

.neighborhood.new-section .map-canvas iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

.neighborhood.new-section .map-list-wrapper .nbp-filter-places {
  width: 100%;
  max-width: 100%;
  overflow: hidden;
}

/* v1: .container.nb-places-list — heading column beside the strip */
.neighborhood.new-section .nbp-list-view-wrap {
  display: flex;
  flex-flow: wrap;
  width: 100%;
  padding: 30px 0;
}

.neighborhood.new-section .nbp-heading-wrap {
  display: flex;
  flex-flow: column;
  justify-content: center;
  width: 20%;
  margin-bottom: 0;
  gap: 10px;
}

.neighborhood.new-section .nbp-heading-wrap .nbp-places-heading {
  margin: 0;
}

/* v1: .nb-places-wrapper — the horizontal scroller. The framework caps this at
   549px and scrolls it vertically; both are undone here. */
.neighborhood.new-section .nbp-places-list {
  width: 80%;
  height: auto;
  max-height: none;
  padding: 0 15px 15px;
  overflow-x: auto;
  overflow-y: hidden;
  white-space: nowrap;
  scrollbar-width: thin;
  /* the arrows just set scrollLeft; the easing lives here, so it also honours
     prefers-reduced-motion without any JS */
  scroll-behavior: smooth;
  /* Cards are a percentage of the strip, so any scroll position that is not a
     whole number of cards leaves a sliced card at both ends — the name reads
     "esh Foods" / "Parkside Provisi". Snapping pins every rest position to a
     card edge, at every width, for both the arrows and a touch swipe. */
  scroll-snap-type: x mandatory;
  scroll-padding-left: 0;
}

@media (prefers-reduced-motion: reduce) {
  .neighborhood.new-section .nbp-places-list {
    scroll-behavior: auto;
  }
}

.neighborhood.new-section .nbp-places-list::-webkit-scrollbar {
  height: 8px;
}

.neighborhood.new-section .nbp-places-list::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.08);
}

.neighborhood.new-section .nbp-places-list::-webkit-scrollbar-thumb {
  background: #9f662d;
}

/* framework makes this a disc-bulleted flex column — back to a plain row */
.neighborhood.new-section .nbp-places-list .nb-places-ul {
  display: block;
  gap: 0;
  margin: 0;
  padding: 0;
  font-size: 0;
  list-style: none;
}

/* v1: 5 cards per view, divided by hairlines */
.neighborhood.new-section .nbp-places-list .nb-places-ul li {
  display: inline-block;
  width: 20%;
  padding: 0 15px;
  border-right: 1px solid rgba(56, 47, 45, 0.35);
  vertical-align: top;
  white-space: normal;
  font-size: 0.778rem;
  scroll-snap-align: start;
}

.neighborhood.new-section .nbp-places-list .nb-places-ul li:last-child {
  border-right: 0;
}

/* the default category is set in the markup, so the list is correct before any
   JS runs; main.js moves this class as the filter changes */
.neighborhood.new-section .nb-places-ul li.hide-place {
  display: none;
}

/* --- Card contents: name over address, as v1 --- */
.neighborhood.new-section .nb-places-ul li a {
  display: block;
  text-decoration: none;
}

.neighborhood.new-section .nb-places-ul .place-name {
  margin: 0 0 10px;
  font-size: 0.889rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 0.05em;
}

.neighborhood.new-section .nb-places-ul .place-address {
  font-size: 0.833rem;
  font-weight: 300;
  line-height: 1.45;
  letter-spacing: 0.02em;
  color: #382f2d;
}

/* --- Strip chevrons (theme-added; the component ships none) --- */
.neighborhood.new-section .nbp-places-scroller {
  display: flex;
  align-items: center;
  width: 80%;
}

/* the list sizes itself inside the scroller now, so the width moves up a level */
.neighborhood.new-section .nbp-places-scroller .nbp-places-list {
  width: auto;
  flex: 1 1 auto;
  min-width: 0;
}

.neighborhood.new-section .nbp-places-nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  background: transparent;
  color: #382f2d;
  font-size: 1.1rem;
  cursor: pointer;
}

/* kept in the layout when disabled so the strip does not shift width */
.neighborhood.new-section .nbp-places-nav[disabled] {
  opacity: 0.25;
  cursor: default;
}
/* ============================================================
   SECTION: NEIGHBORHOOD MAP + PLACES — END
   ============================================================ */

/* ============================================================
   SECTION: INNER PAGE WRAPPER + INTRO TYPE 1 — START

   NOTE: the .page-hero-bg rules below are currently DORMANT. amenities.html was
   the only page using that div and now renders the .inner-hero-section
   component instead (see SECTION: INNER HERO BANNER above). Kept, not deleted —
   the neighborhood page may still want this photo-behind-the-intro treatment.

   v1 shape (.inner-page-body-wrapper + .page-hero-bg + .inner-page-intro):
   ONE dark wrapper holds the page-hero photo, the intro and the tabs, so the
   photo runs continuously behind all of them and fades to black. The photo is
   a fixed 56vw band anchored to the top of the wrapper — it does not belong
   to the intro and does not shrink with the copy.
   ============================================================ */
.inner-page-body-wrapper {
  position: relative;
  overflow: hidden;
}

/* v1: .page-hero-bg */
.inner-page-body-wrapper .page-hero-bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 56vw;
  overflow: hidden;
}

.inner-page-body-wrapper .page-hero-img {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

/* v1: .page-hero-bg::before — bottom fade over the lower 60% only, so the
   top of the photo stays clean */
.inner-page-body-wrapper .page-hero-bg::before {
  content: "";
  display: block;
  position: absolute;
  z-index: 1;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 60%;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 25%, #000000 80%);
}

/* v1: .page-hero-bg::after — large radial vignette; this is what makes the
   photo read as emerging from black. A plain linear fade alone looks flat. */
.inner-page-body-wrapper .page-hero-bg::after {
  content: "";
  display: block;
  position: absolute;
  z-index: 1;
  top: calc(50% - 225px);
  left: 50%;
  width: 120%;
  height: 100vw;
  border-radius: 50%;
  background: radial-gradient(
    ellipse at center,
    #000000 0,
    rgba(0, 0, 0, 0.25) 100%
  );
  transform: translate(-50%, -50%);
  opacity: 0.85;
}

/* --- Intro: text only, centred over the photo ---
   v1: .inner-page-intro { max-width:665px; margin:0 auto;
   padding:180px 20px 90px; text-align:center; z-index:5 } */
.intro-type-1 {
  position: relative;
  z-index: 5;
  background: transparent; /* the wrapper carries the ground */
  padding-top: 180px;
  padding-bottom: 90px;
}

/* the photo now lives on the wrapper, so this component's own image slot is
   unused on this page */
.intro-type-1 .left-col {
  display: none;
}

.intro-type-1 .intro-container {
  display: block;
}

.intro-type-1 .right-col {
  width: 100%;
}

.intro-type-1 .content-wrapper {
  width: 100%;
  max-width: 665px;
  margin: 0 auto;
  padding: 0 20px;
  text-align: center;
}

/* v1: h1.inner-page-title { margin: 0 0 25px } */
.intro-type-1 .intro-heading .section-title {
  margin: 0 0 25px;
}

/* v1: .inner-page-intro h2.inner-page-intro-title */
.intro-type-1 .intro-heading .section-subtitle {
  margin: 0 0 15px;
  line-height: 1.64;
}

/* v1: .inner-page-intro-content a */
.intro-type-1 .intro-content .section-content a {
  color: #b98a52;
  text-decoration: underline;
}

.intro-type-1 .section-buttons {
  justify-content: center;
  margin-top: 25px;
}
/* ============================================================
   SECTION: INNER PAGE WRAPPER + INTRO TYPE 1 — END
   ============================================================ */
/* ============================================================
   SECTION: AMENITIES TABS + MASONRY — START
   Ported from live-html-css-lvl29's .amenities-page-gallery. One dark
   section, two tab panes; each pane keeps this theme's two-column
   amenities markup and adds the masonry photo gallery below it.
   The masonry is v1's exact nth-child recipe: two half-width tiles on the
   first row (the gap beside #1 is where the LVL29 watermark sits), thirds
   at 7-9, halves at 10-11, then a uniform third-width grid from 12 on.
   ============================================================ */
/* transparent, not black: the photo band on .inner-page-body-wrapper runs
   behind this section too, exactly as on the live site. A solid background
   here would cut the photo off at the tabs. */
.amenities-page-gallery {
  position: relative;
  padding-bottom: 60px;
  background-color: transparent;
}

/* --- Tabs --- */
.amenities-page-gallery ul.ct-tabs {
  position: relative;
  z-index: 9;
  display: block;
  width: 100%;
  max-width: 1060px;
  margin: 0 auto;
  padding: 25px 0;
  border-top: 1px solid;
  text-align: center;
}

.amenities-page-gallery ul.ct-tabs > li {
  display: inline-block;
  width: auto;
  min-width: 120px;
  margin: 5px;
  padding: 9px 15px;
  font-family: "Playfair Display", Georgia, serif;
  font-size: 1.429rem;
  font-weight: 700;
  line-height: 1;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.amenities-page-gallery .ct-tabs-container {
  position: relative;
  width: 1060px;
  max-width: 100%;
  margin: 0 auto;
}

/* panes: collapsed to zero height rather than display:none, so the
   masonry scale-in transition has something to animate from */
.amenities-page-gallery .tab-content {
  position: relative;
  z-index: 9;
  height: 0;
  opacity: 0;
  overflow: hidden;
}

.amenities-page-gallery .tab-content.current {
  height: auto;
  opacity: 1;
}

/* dotted pattern decorations behind the panes */
.amenities-page-gallery .ct-tabs-container::before,
.amenities-page-gallery .ct-tabs-container::after {
  content: "";
  display: block;
  position: absolute;
  top: 115px;
  left: calc(50% - 150px);
  width: 100px;
  height: 100%;
  max-height: 750px;
  background: url("../images/icons/pattern-dots.svg") no-repeat 50%;
  transform: translateX(-50%);
}

.amenities-page-gallery .ct-tabs-container::after {
  top: 275px;
  left: calc(50% + 150px);
}

/* --- Feature list --- */

/* DOUBLE BULLET. This list sits inside #community-amenities, which is
   .amenities-section nested inside .amenities-page-gallery — so the framework's
   `.amenities-section .amenities-grid-wrap ul.amenities-grid li { list-style:
   disc }` (component-common.css:1974) applies as well as the ::before dot
   below, and every item drew two markers. The framework selector is (0,3,2),
   so the native marker can only be switched off by matching it: three classes
   plus ul + li, later in the file. Its `padding-left: 20px` on the <ul>
   (:1969) goes with it, so the theme's dot lines up with the copy above
   instead of being pushed in by the marker gutter. */
.amenities-page-gallery .amenities-grid-wrap ul.amenities-grid > li {
  list-style: none;
  /* the same framework rule sets `padding: 0 0 8px 0`, which out-ranks the
     18px gutter below — so the absolutely-placed dot was landing on top of the
     first character. Restored at the winning specificity. */
  padding-left: 18px;
}

.amenities-page-gallery .amenities-grid-wrap ul.amenities-grid {
  padding-left: 0;
}

.amenities-page-gallery ul.amenities-grid {
  padding: 0;
}

.amenities-page-gallery ul.amenities-grid > li {
  position: relative;
  width: 100%;
  padding: 0 0 8px 18px;
  font-weight: 300;
  line-height: 1.5;
}

.amenities-page-gallery ul.amenities-grid > li::before {
  content: "";
  position: absolute;
  top: 9px;
  left: 0;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #ffffff;
}

/* --- Masonry gallery --- */
.amenities-page-gallery .amenities-gallery {
  position: relative;
  width: 100%;
  margin: 60px 0;
}

.amenities-page-gallery svg.amnety-svg {
  position: absolute;
  width: 515px;
  max-width: 60%;
  margin-top: 55px;
}

.amenities-page-gallery svg.amnety-svg * {
  fill: hsla(0, 0%, 100%, 0.15);
}

.amenities-page-gallery ul.modular-gallery-ul {
  width: 100%;
  margin: 100px auto 0;
  padding: 0 20px;
  font-size: 0;
}

.amenities-page-gallery ul.modular-gallery-ul li.modular-image-container {
  position: relative;
  display: inline-block;
  vertical-align: top;
  width: calc(25% - 30px);
  height: auto;
  min-height: 200px;
  margin: 0 15px 30px;
  background-size: cover;
  background-position: center center;
  transform: scale(0.5);
  transition: all 0.5s ease 0s;
}

.amenities-page-gallery .tab-content.current ul.modular-gallery-ul li.modular-image-container {
  transform: scale(1);
}

.amenities-page-gallery ul.modular-gallery-ul li.modular-image-container a.modular_gallery_image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.amenities-page-gallery ul.modular-gallery-ul li.modular-image-container img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* first-cycle artistic offsets — the gap beside #1 is the watermark */
.amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(1) {
  float: left;
  width: calc(50% - 30px);
  height: 320px;
  margin-left: calc(50% + 15px);
}

.amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(2) {
  float: left;
  width: calc(50% - 30px);
  height: 320px;
}

.amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(7),
.amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(8),
.amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(9) {
  width: calc(33.33% - 30px);
}

.amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(10),
.amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(11) {
  width: calc(50% - 30px);
  height: 350px;
}

/* from #12 on: clean uniform grid */
.amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(n + 12) {
  float: none;
  width: calc(33.33% - 30px);
  height: 240px;
  margin-left: 15px;
}

.amenities-page-gallery .amenities-gallery ul::after {
  display: table;
  content: " ";
  clear: both;
}

/* --- The two-column pane content, on the dark ground --- */
.amenities-page-gallery .amenities-section {
  padding-top: 0;
  padding-bottom: 0;
}

.amenities-page-gallery .amenities-container {
  display: flex;
  flex-flow: wrap;
  align-items: flex-start;
}

.amenities-page-gallery .amenities-container .left-col {
  width: 62%;
}

.amenities-page-gallery .amenities-container .right-col {
  width: 38%;
  padding-left: 60px;
}

/* The feature list is two columns in this narrower right-hand column, so the
   items need room for the bullet — without this the dot sits on top of the
   first character. */
.amenities-page-gallery ul.amenities-grid {
  column-count: 2;
  column-gap: 24px;
}

.amenities-page-gallery ul.amenities-grid > li {
  break-inside: avoid;
  padding-left: 16px;
}

.amenities-page-gallery .img-wrapper img {
  width: 100%;
  height: auto;
}

.amenities-page-gallery .amenities-heading .small-heading {
  display: block;
  margin-bottom: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: #9f662d;
}

/* the pane markup carries text-color-dark, unreadable on the dark ground */
.amenities-page-gallery .amenities-heading .section-title,
.amenities-page-gallery .amenities-heading .section-subtitle,
.amenities-page-gallery .section-content,
.amenities-page-gallery .section-content p,
.amenities-page-gallery .list-content,
.amenities-page-gallery ul.amenities-grid > li {
  color: #ffffff;
}
/* ============================================================
   SECTION: AMENITIES TABS + MASONRY — END
   ============================================================ */

/* ============================================================
   SECTION: GALLERY PAGE — START
   The Swifty gallery component (gallery-page.html) on v1's dark ground.

   component-common.css:2599-2673 already provides: .gallery-grid as a
   flex-wrap row with gap:24px, the filter button shell, .gallery-card img
   object-fit, the .tab-content / .tab-content.active show-hide, and the ≤768px
   swap to the dropdown + slick carousel. None of that is repeated here.

   What the framework does NOT provide, and what this block exists for:
     1. .gallery-card has no width and no height above 1024px. The grid is a
        flex row with a gap but the cards have no flex-basis, so each <a>
        collapses to its image's intrinsic width — and img{height:100%}
        collapses with no height on the card. This is the big one.
     2. .filter-btn.active has no styling at all, only cursor:pointer on hover.
     3. Nothing styles the video / virtual-tour cards.
   ============================================================ */

/* --- Grid --- */
.gallery-section.new-section .gallery-container {
  position: relative;
  z-index: 2;
}

/* 3-up. The 16px subtracted is 2/3 of the framework's 24px gap, which is what
   three columns share between them. */
.gallery-section.new-section .gallery-card {
  flex: 0 0 calc(33.333% - 16px);
  max-width: calc(33.333% - 16px);
  /* the thumbnails are all 700x394 — matching that keeps rows flush without
     hardcoding a pixel height */
  aspect-ratio: 700 / 394;
}

.gallery-section.new-section .gallery-card img {
  transition: transform 0.5s ease;
}

.gallery-section.new-section .gallery-card:hover img {
  transform: scale(1.05);
}

/* --- Filter buttons ---
   v1's ct-tabs look: solid white pill with black text, gold with white text
   when active, sitting under a hairline rule. Colour is declared by the
   dynamic classes on the markup (bg-light / text-color-primary /
   bg-secondary-active / text-color-light-active) — the same set the amenities
   tabs use — so the backend can still re-theme it. */
.gallery-section.new-section .filter-categories-wrapper a.filter-btn {
  border-radius: 0;
  font-family: "Playfair Display", Georgia, serif;
  /* v1: ul.ct-tabs > li { font-size: 20px } — 20/18 at the root step */
  font-size: 1.111rem;
  font-weight: 700;
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  transition: all 0.3s ease;
}

/* component-common.css:2620 sets `background: transparent` on these anchors
   with THREE-class specificity, which beats the single-class bg-* utilities in
   dynamic-styles.css. Without the two rules below the pills render transparent
   and their black text disappears into the dark ground.

   These re-assert the SAME two utilities at a specificity that wins. The values
   are copied from dynamic-styles.css (.bg-light #ffffff, .bg-secondary-active
   #9f662d) — that file has no custom properties, only hardcoded hex, so there
   is nothing to reference. If the palette changes there, change it here too. */
.gallery-section.new-section .filter-categories-wrapper a.filter-btn.bg-light {
  background-color: #ffffff;
}

.gallery-section.new-section .filter-categories-wrapper a.filter-btn.bg-secondary-active.active {
  background-color: #9f662d;
}

/* v1: ul.ct-tabs sits under a full-width hairline with generous breathing room */
.gallery-section.new-section .filter-categories {
  padding: 25px 0;
  border-top: 1px solid #ffffff;
}

/* --- Video and virtual-tour cards --- */
.gallery-section.new-section .vr-tour-container {
  display: flex;
  flex-flow: wrap;
  gap: 24px;
  width: 100%;
  padding: 0;
}

.gallery-section.new-section .single-virtual-tour {
  flex: 0 0 calc(33.333% - 16px);
  max-width: calc(33.333% - 16px);
  border: 1px solid;
}

.gallery-section.new-section .vt-img-wrapper {
  position: relative;
  aspect-ratio: 700 / 394;
  overflow: hidden;
}

.gallery-section.new-section .vt-img-wrapper img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* play affordance over the video thumbnails only */
.gallery-section.new-section .single-gallery-video .vt-img-wrapper::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  transform: translate(-50%, -50%);
}

.gallery-section.new-section .single-gallery-video .vt-img-wrapper svg,
.gallery-section.new-section .vt-btns svg {
  width: 18px;
  height: 18px;
  fill: currentColor;
  vertical-align: middle;
}

.gallery-section.new-section .vt-info-wrapper {
  padding: 20px;
}

.gallery-section.new-section .vt-title {
  margin: 0 0 15px;
  font-size: 1.111rem;
}

.gallery-section.new-section .vt-btns {
  display: flex;
  flex-flow: wrap;
  gap: 10px;
}

.gallery-section.new-section .vt-btns .btn {
  font-size: 0.778rem;
}

/* component-common.css:2651 pins every .swi in this section to a fixed 20px,
   which is nearly double the button label (0.778rem ≈ 11px) — the icon ended up
   dwarfing the text. em ties it to the button's own size, so it stays in
   proportion at every breakpoint as the root font-size steps down.
   The margin also moves to the left: the icon follows the label here, so the
   framework's margin-right was padding empty space. */
.gallery-section.new-section .vt-btns .btn .swi {
  margin-right: 0;
  margin-left: 6px;
  font-size: 1.15em;
  vertical-align: middle;
}

/* --- v1's dotted decoration behind the grid --- */
.gallery-section.new-section .gallery-tabs-content {
  position: relative;
}

.gallery-section.new-section .gallery-tabs-content::before,
.gallery-section.new-section .gallery-tabs-content::after {
  content: "";
  display: block;
  position: absolute;
  z-index: -1;
  width: 100px;
  height: 100%;
  max-height: 750px;
  background: url(../images/icons/pattern-dots.svg) no-repeat 50%;
}

.gallery-section.new-section .gallery-tabs-content::before {
  top: 115px;
  left: calc(50% - 150px);
}

.gallery-section.new-section .gallery-tabs-content::after {
  top: calc(50% + 275px);
  left: calc(50% + 150px);
}
/* ============================================================
   SECTION: GALLERY PAGE — END
   ============================================================ */

/* ============================================================
   SECTION: TOUR PAGE — START
   The virtual-tour cards grid (tour-page.html, GRID LAYOUT VARIANT) on the
   dark inner-page wrapper.

   Unlike the form and gallery components, component-common.css supplies almost
   nothing here: its only base rule for this component is
   `.vr-tour-container .vt-img-wrapper img` (:2900, the object-fit). There is no
   grid rule, no .type-grid rule, no card, no button layout — all of it is
   below. The two other framework mentions are inside media queries and are
   scoped elsewhere (:4105 to .gallery-wrap, :4147 to a 375px block).

   These rules deliberately mirror the gallery page's VR card styling
   (SECTION: GALLERY PAGE), which is scoped to .gallery-section and so does not
   reach this page. Keep the two in step if either changes.
   ============================================================ */
/* The inner hero is a BACKDROP here, not a band: .inner-page-body-wrapper
   .inner-hero-section is absolutely positioned (see SECTION: INNER HERO
   BANNER), so the page content sits over the photo. On amenities and gallery
   the intro block carries 180px of top padding to clear the fixed header and
   sit on the photo; this page has no intro, so the tours section has to
   provide that clearance itself — without it the heading collides with the
   header and the cards ride up over the hero. */
.page-tr .vr-tour-section {
  position: relative;
  z-index: 5;
  padding-top: 180px;
}

.page-tr .vt-section-content {
  margin-bottom: 40px;
}
.new-section .vt-section-content h2.section-title,
.new-section .vt-section-content h3.section-subtitle {
  margin-left: auto;
  margin-right: auto;
}

.page-tr .vt-section-content.center-text {
  text-align: center;
}

.page-tr .vr-tour-container.type-grid {
  display: flex;
  flex-flow: wrap;
  gap: 24px;
  width: 100%;
}

.page-tr .single-virtual-tour {
  flex: 0 0 calc(33.333% - 16px);
  max-width: calc(33.333% - 16px);
  border: 1px solid;
}

.page-tr .vt-img-wrapper {
  position: relative;
  aspect-ratio: 700 / 394;
  overflow: hidden;
}

.page-tr .vt-info-wrapper {
  padding: 20px;
}

.page-tr .vt-title {
  margin: 0 0 15px;
  font-size: 1.111rem;
}

.page-tr .vt-btns {
  display: flex;
  flex-flow: wrap;
  gap: 10px;
}

.page-tr .vt-btns .btn {
  font-size: 0.778rem;
}

/* component-common.css pins .swi to a fixed 20px inside these components,
   which is nearly double the button label — the same problem the gallery's
   tour buttons had. em keeps it in proportion as the root size steps down. */
.page-tr .vt-btns .btn .swi {
  margin-left: 6px;
  font-size: 1.15em;
  vertical-align: middle;
}
/* ============================================================
   SECTION: TOUR PAGE — END
   ============================================================ */

/* ============================================================
   SECTION: LIGHT INNER PAGES — START
   Shared ground + hero treatment for faq.html, resources.html and
   resident.html, taken from live-html-css-lvl29/faq.html.

   These three read as one family: a photographic banner with the title set
   left in the container, then content on white cards with a soft drop shadow
   over a white ground — not the black ground the other inner pages use.

   Done ENTIRELY in CSS, by request. The markup still declares
   `bg-primary text-color-light` on the wrapper, and text-color-light on the
   headings, answers and buttons inside; that is the backend's colour contract
   and is left untouched. So every rule here has to out-rank a dynamic class,
   which is why each carries the page class too —
   `.inner-page-body-wrapper.page-fq` (0,2,0) beats `.bg-primary` (0,1,0), and
   `.page-fq .x.text-color-light` (0,3,0) beats `.text-color-light` (0,1,0).
   If the backend is later re-themed to emit bg-light / text-color-dark on
   these pages, the overrides go redundant rather than wrong.

   Palette used: light #ffffff, dark #502c1e, secondary #9f662d,
   accent #e2ded5. v1's card shadow is 0 5px 16px 0 #080f340f.
   ============================================================ */

/* ----- the ground ----- */
.inner-page-body-wrapper.page-fq,
.inner-page-body-wrapper.page-rs,
.inner-page-body-wrapper.page-rd {
  background-color: #ffffff;
  color: #502c1e;
}

/* ----- the hero, as a band -----
   The base rule (SECTION: INNER HERO BANNER) absolutely positions
   .inner-hero-section so page content sits over the photo. That is right for
   amenities/gallery/neighborhood, where an intro block overlays it; here it
   only buried the title behind the cards. Taken back into the flow, at v1's
   500px (.inner-page-banner.faq-banner, live style.css:1306). Same two-class
   specificity as the base rule but later in the file, so this wins. */
.page-fq .inner-hero-section,
.page-rs .inner-hero-section,
.page-rd .inner-hero-section,
.page-bl .inner-hero-section,
.page-bs .inner-hero-section {
  position: relative;
  height: 500px;
  overflow: hidden;
}

/* The base hero fades to black at the bottom (::before) and adds a black
   vignette (::after) so the photo reads as emerging from the black wrapper.
   Against white that fade lands as a dirty grey edge, so both are dropped and
   replaced with v1's flat scrim over the whole banner
   (.faq-banner .inner-wrapper-overlay). */
.page-fq .inner-hero-section::before,
.page-rs .inner-hero-section::before,
.page-rd .inner-hero-section::before,
.page-bl .inner-hero-section::before,
.page-bs .inner-hero-section::before {
  height: 100%;
  background: rgba(0, 0, 0, 0.45);
}

.page-fq .inner-hero-section::after,
.page-rs .inner-hero-section::after,
.page-rd .inner-hero-section::after,
.page-bl .inner-hero-section::after,
.page-bs .inner-hero-section::after {
  display: none;
}

/* Show the hero title. style.css:1058 hides .inner-hero-content for every page
   in this wrapper — correct where an intro block carries the page title, but
   these three have no intro, so the hero carries it. Set left in the container
   rather than centred, matching v1. Same three-class specificity as the rule it
   overrides, later in the file. */
.page-fq .inner-hero-section .inner-hero-content,
.page-rs .inner-hero-section .inner-hero-content,
.page-rd .inner-hero-section .inner-hero-content,
.page-bl .inner-hero-section .inner-hero-content,
.page-bs .inner-hero-section .inner-hero-content {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 2;
  width: 100%;
  /* mirrors .container (component-main.css:86) so the title lines up with the
     card grid below it */
  max-width: 1200px;
  padding: 0 16px;
  transform: translate(-50%, -50%);
  text-align: left;
}

.page-fq .inner-hero-section .text-wrap,
.page-rs .inner-hero-section .text-wrap,
.page-rd .inner-hero-section .text-wrap,
.page-bl .inner-hero-section .text-wrap,
.page-bs .inner-hero-section .text-wrap {
  position: relative;
  display: block;
  padding: 0;
}

/* v1 has no plate behind the title — the scrim above does that job for the
   whole banner. The div stays in the markup (the backend colours it), it is
   just not painted here. */
.page-fq .inner-hero-section .text-overlay,
.page-rs .inner-hero-section .text-overlay,
.page-rd .inner-hero-section .text-overlay,
.page-bl .inner-hero-section .text-overlay,
.page-bs .inner-hero-section .text-overlay {
  display: none;
}

/* margin reset only — typo.css owns h1.inner-hero-title's size */
/* typo.css sizes .inner-hero-title for a banner that sits BEHIND an intro
   block, where the title is hidden anyway. Here it is the only thing on the
   photo, so it is stepped up to v1s display size (.inner-page-title renders
   around 62px at 1440; 4.4rem against typo.css 14px root matches it). */
/* .page-fq .inner-hero-section .inner-hero-title,
.page-rs .inner-hero-section .inner-hero-title,
.page-rd .inner-hero-section .inner-hero-title,
.page-bl .inner-hero-section .inner-hero-title,
.page-bs .inner-hero-section .inner-hero-title {
  position: relative;
  z-index: 1;
  margin: 0;
  font-size: 4.4rem;
  line-height: 1.1;
}
 */
/* ----- the shared card surface -----
   v1's .faq-section .question-wrap: white, soft shadow, and a 2px transparent
   border that goes bronze on the open/hover state so nothing shifts. */
.page-fq .new-section.faq-section .faq-item,
.page-rs .single-resource-item,
.page-rd .single-resident-section {
  border: 2px solid transparent;
  background-color: #ffffff;
  box-shadow: 0 5px 16px 0 #080f340f;
  transition: border-color 0.3s ease, transform 0.3s ease;
}

.page-fq .new-section.faq-section .faq-item:hover,
.page-fq .new-section.faq-section .faq-item.open,
.page-rs .single-resource-item:hover,
.page-rd .single-resident-section:hover {
  border-color: #9f662d;
}
/* ============================================================
   SECTION: LIGHT INNER PAGES — END
   ============================================================ */

/* ============================================================
   SECTION: RESIDENT PAGE — START
   The resident hub tiles (resources-resident-faq.html, #resident).

   component-common.css supplies only the grid and the tile's flex
   (:2556-2564 — `.resident-container { display:grid; grid-template-columns:
   repeat(3,1fr) }` and `.single-resident-section { display:flex;
   align-items:center; position:relative }`), plus 2-col at 1024 (:3330) and
   1-col at 480 (:4074). It gives the tile no surface, no padding, no icon
   sizing and no link styling.

   The ground, the hero band and the white card surface are shared with
   faq.html and resources.html — see SECTION: LIGHT INNER PAGES above. Only the
   tile internals are here.

   NOTE the framework grid has no gap, so the tiles would butt together; the
   gap is added below.
   ============================================================ */

.page-rd .resident-container {
  gap: 24px;
}

.page-rd .single-resident-section {
  padding: 32px 38px;
}

.page-rd .single-resident-section:hover {
  transform: translateY(-4px);
}

.page-rd .resident-section-content {
  width: 100%;
}

.page-rd .icon-title-wrap {
  display: flex;
  align-items: center;
  gap: 15px;
  margin-bottom: 15px;
}

/* the inline SVGs were switched to fill:currentColor in the markup, so they
   take this colour rather than the black they ship with. The span declares
   text-color-light for the old black ground — out-ranked here. */
.page-rd .res-head-icon.text-color-light {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  color: #9f662d;
}

/* The six inline SVGs this component ships are broken placeholder art, not a
   styling problem: the path data is truncated (d attributes of 577, 419, 341,
   178, 168 and 110 characters for what should be six complete icons — each
   pair is the previous one cut shorter), and two of them carry fill="none" on
   the <svg> with an empty fill="" on the path. They render as a blob, a
   sliver, or nothing at all. Verified path-for-path against the untouched
   source, resources-resident-faq.html: this is how the component ships, not
   something the build introduced.

   The backend supplies the real icons in production. Until then the broken
   SVGs are hidden and a SwiftyIcons glyph is drawn in their place, so the page
   reads correctly without editing the markup.

   CAVEAT: the tiles carry no per-tile class (unlike the resources grid, which
   has class-one..class-six), so the mapping has to go by position. If the
   backend reorders or adds tiles this map is wrong — which is the argument for
   repairing the SVGs at source instead. */
.page-rd .res-head-icon svg {
  display: none;
}

.page-rd .res-head-icon::before {
  font-family: "SwiftyIcons";
  font-size: 32px;
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  line-height: 1;
  text-transform: none;
  speak: never;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.page-rd .single-resident-section:nth-child(1) .res-head-icon::before {
  content: "\e970"; /* swi-help — FAQs */
}

.page-rd .single-resident-section:nth-child(2) .res-head-icon::before {
  content: "\e904"; /* swi-resources — Resources */
}

.page-rd .single-resident-section:nth-child(3) .res-head-icon::before {
  content: "\e94f"; /* swi-card — Pay Rent */
}

.page-rd .single-resident-section:nth-child(4) .res-head-icon::before {
  content: "\e903"; /* swi-refresh — Renew Your Lease */
}

.page-rd .single-resident-section:nth-child(5) .res-head-icon::before {
  content: "\e909"; /* swi-setting — Maintenance */
}

.page-rd .single-resident-section:nth-child(6) .res-head-icon::before {
  content: "\e94c"; /* swi-calendar — Resident Events */
}

.page-rd .icon-title-wrap .section-title.text-color-light {
  margin: 0;
  color: #502c1e;
  font-size: 1.333rem;
}

.page-rd .single-resident-section:hover .section-title.text-color-light {
  color: #9f662d;
}

.page-rd .subheading-link-wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 15px;
}

.page-rd .subheading-link-wrap.text-color-light .section-subtitle {
  margin: 0;
  color: rgba(80, 44, 30, 0.75);
  font-size: 0.889rem;
  font-weight: 300;
}

/* v1's chevron disc, at the smaller size this tile calls for */
.page-rd a.resident-section-link {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1px solid #9f662d;
  border-radius: 50%;
  color: #9f662d;
  transition: all 0.3s ease;
}

.page-rd a.resident-section-link:hover {
  background-color: #9f662d;
  color: #ffffff;
}

/* The chevron sat ~2.5px high inside its disc. The link centres its children,
   but .res-link-icon was a block whose line box (24.1px, from .swi's
   line-height: 1.2 at swityicons.css:19) is taller than the 17px glyph, and an
   inline glyph sits on that line box's baseline rather than in its middle — so
   centring the SPAN did not centre the ICON. Making the span a flex box and
   collapsing the glyph's line-height removes the baseline from the equation. */
.page-rd .resident-section-link .res-link-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.page-rd .resident-section-link .swi {
  display: block;
  line-height: 1;
}

/* the label is for screen readers only */
.page-rd .resident-section-link .screen-reader-text {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* ============================================================
   SECTION: RESIDENT PAGE — END
   ============================================================ */


/* ============================================================
   SECTION: RESOURCES PAGE — START
   The resident-resources grid (resources-resident-faq.html,
   #resources-section).

   component-common.css styles NOTHING for this component — there is no rule
   anywhere for .resources-section, .single-resource-item, .resource-header,
   .resource-number, .resource-title, .resource-content or .resource-link. Its
   only "resource" matches belong to .fixed-links-section, a different
   component. So unlike the form and gallery sections, none of this is an
   override: it is the component's only styling.

   The ground, the hero band and the white card surface are shared with
   faq.html and resident.html — see SECTION: LIGHT INNER PAGES above. Only the
   grid and the card's internals are here.
   ============================================================ */

/* the grid is a normal section — no header clearance needed, because the hero
   band now occupies that space */
.page-rs .resources-section {
  position: relative;
  z-index: 5;
}

.page-rs .resources-container {
  display: flex;
  flex-flow: wrap;
  gap: 24px;
  width: 100%;
}

.page-rs .single-resource-item {
  display: flex;
  flex-flow: column;
  flex: 0 0 calc(33.333% - 16px);
  max-width: calc(33.333% - 16px);
  padding: 32px 38px;
}

.page-rs .single-resource-item:hover {
  transform: translateY(-4px);
}

/* the anchor wraps only the header, so it must not collapse the card */
.page-rs .single-resource-item .external_link {
  display: block;
  text-decoration: none;
}

.page-rs .resource-header {
  display: flex;
  align-items: baseline;
  gap: 15px;
  margin-bottom: 20px;
  padding-bottom: 20px;
  border-bottom: 1px solid #e2ded5;
}

/* the oversized index is what gives this grid its structure */
.page-rs .resource-number {
  flex: 0 0 auto;
  font-family: "Playfair Display", Georgia, serif;
  font-size: 2.222rem;
  font-weight: 700;
  line-height: 1;
  color: #9f662d;
}

/* the markup declares text-color-light for the old black ground; three classes
   to out-rank it without touching the HTML */
.page-rs .resource-title.text-color-light {
  margin: 0;
  color: #502c1e;
  font-family: "Playfair Display", Georgia, serif;
  font-size: 1.222rem;
  font-weight: 700;
  line-height: 1.25;
}

.page-rs .single-resource-item:hover .resource-title.text-color-light {
  color: #9f662d;
}

/* push the link to the foot of every card so the row stays even */
.page-rs .resource-content {
  display: flex;
  flex-flow: column;
  flex: 1 1 auto;
}

.page-rs .resource-content .section-content {
  flex: 1 1 auto;
  margin-bottom: 20px;
}

.page-rs .resource-content .section-content p {
  margin: 0;
  color: #502c1e;
  font-weight: 300;
  line-height: 1.5;
}

.page-rs a.resource-link {
  align-self: flex-start;
  padding-bottom: 4px;
  border-bottom: 1px solid #9f662d;
  color: #9f662d;
  font-size: 0.778rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  transition: all 0.3s ease;
}

.page-rs a.resource-link:hover {
  border-bottom-color: #502c1e;
  color: #502c1e;
}
/* ============================================================
   SECTION: RESOURCES PAGE — END
   ============================================================ */


/* ============================================================
   SECTION: FAQ PAGE — START
   The #faq-section component (resources-resident-faq.html) wearing v1's
   accordion design (live-html-css-lvl29/faq.html, style.css:1340-1402).

   The ground, the hero band and the white card surface are shared with
   resources.html and resident.html — see SECTION: LIGHT INNER PAGES above.
   What is left here is the accordion itself plus the two controls the v1 page
   does not have at all (search bar and category buttons), styled to the same
   white-card language.

   What component-common.css already owns — DO NOT restate any of it here:
     :2213-2236  .faq-item margin, .faq-answer display:none,
                 .faq-item.open .faq-answer display:block, the 180deg icon
                 rotation, and the .faq-question flex row. The open/closed
                 state is a `display` swap on `.open`, NOT v1's `.active` +
                 slideToggle — the JS in main.js toggles `.open` to match.
     :2178       .minus-plus is display:none, so chevron-type-1 is the icon
                 actually in play.
     :2193-2210  the search bar's flex row and .search-faq input reset.
     :2238-2262  .faq-categories / .faq-categories-wrapper centring.
     :2264-2290  the mobile <select>, .no-faq-msg and `.active { border: 3px }`.
     :3176       search-bar padding at 1024.
     :3999-4033  at 767 the button row is hidden and the <select> shown, and
                 question/answer/search padding is cut — all with !important.

   Two framework paths corrected rather than merely coloured:
     - the <select> chevron at :2275 points at `../../images/faq-chevron.svg`,
       which resolves to lvl29-v2/images/ — a directory that does not exist.
       Replaced below with an inline data-URI arrow.
     - `.active { border: 3px solid }` (:2288) is 3px against the 1px resting
       border, so activating a category nudged the whole row. Held at 1px here
       and the active state carried by fill instead.
   ============================================================ */

/* ----- search bar ----- */
.page-fq .new-section.faq-section .faq-search-bar {
  margin-bottom: 30px;
  border: 1px solid #e2ded5;
  background-color: #ffffff;
  box-shadow: 0 5px 16px 0 #080f340f;
  transition: border-color 0.3s ease;
}

.page-fq .new-section.faq-section .faq-search-bar:focus-within {
  border-color: #9f662d;
}

.page-fq .new-section.faq-section .faq-search-bar .swi-search {
  flex: 0 0 auto;
  color: #9f662d;
  font-size: 1rem;
}

.page-fq .faq-search-bar input.search-faq.text-color-light {
  color: #502c1e;
}

/* the framework input is background:transparent, so the only thing missing is
   a placeholder colour that reads on white */
.page-fq .faq-search-bar input.search-faq::placeholder {
  color: rgba(80, 44, 30, 0.5);
  opacity: 1;
}

.page-fq .faq-search-bar input.search-faq::-webkit-input-placeholder {
  color: rgba(80, 44, 30, 0.5);
}

/* ----- category buttons ----- */
.page-fq .new-section.faq-section .faq-categories {
  flex-wrap: wrap;
  margin-bottom: 40px;
}

.page-fq .new-section.faq-section .faq-categories-wrapper {
  gap: 12px;
}

.page-fq .new-section.faq-section .faq-categories button {
  padding: 12px 26px;
  border: 1px solid #e2ded5;
  box-shadow: 0 5px 16px 0 #080f340f;
  font-size: 0.833rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: all 0.3s ease;
}

.page-fq .new-section.faq-section .faq-categories button.text-color-light {
  color: #502c1e;
}

.page-fq .new-section.faq-section .faq-categories button:hover {
  border-color: #9f662d;
  color: #9f662d;
}

/* hold the resting border width through the active state (see notes above);
   the border colour comes from the dynamic .border-color-secondary-active */
.page-fq .new-section.faq-section .faq-categories button.active {
  border-width: 1px;
}

/* The markup carries bg-secondary-active, but dynamic-styles.css:39-40 is
   `.bg-secondary-active.active` (0,2,0) and loses to the framework's
   `.new-section.faq-section .faq-categories button { background: transparent }`
   (0,3,1) at :2245. Same collision the gallery filter buttons hit. Re-asserted
   here at matching specificity so the active pill actually fills; the hex has
   to be repeated because the dynamic rule it stands in for cannot win. The
   markup's text-color-light is finally correct in this state, so it is let
   through rather than overridden. */
.page-fq .new-section.faq-section .faq-categories button.bg-secondary-active.active {
  background-color: #9f662d;
}

.page-fq .new-section.faq-section .faq-categories button.text-color-light.active {
  color: #ffffff;
}

/* ----- mobile category dropdown ----- */
.page-fq .new-section.faq-section .faq-categories-dropdown select {
  border: 1px solid #e2ded5;
  border-radius: 0;
  background-color: #ffffff;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239f662d' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 16px 16px;
  box-shadow: 0 5px 16px 0 #080f340f;
  color: #502c1e;
}

/* ----- accordion card -----
   the white surface and the bronze open/hover border are shared (see LIGHT
   INNER PAGES); only v1's spacing and type live here */
.page-fq .new-section.faq-section .faq-item {
  position: relative;
  margin-bottom: 10px;
}

.page-fq .new-section.faq-section .faq-question {
  gap: 24px;
  padding: 32px 38px;
  border: 0;
  background: transparent;
  color: #502c1e;
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 1px;
  line-height: 1.5;
}

.page-fq .new-section.faq-section .faq-item.open .faq-question,
.page-fq .new-section.faq-section .faq-question:hover {
  color: #9f662d;
}

/* v1's 50px chevron disc: white with the same card shadow while closed, filled
   bronze when open. The framework rotates it 180deg on .open (:2225) — v1
   rotates its right-pointing arrow 90deg for the same effect. */
.page-fq .new-section.faq-section .faq-question .chevron-type-1 {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background-color: #ffffff;
  box-shadow: 0 5px 16px 0 #080f340f;
  color: #9f662d;
  font-size: 0.778rem;
  /* .swi ships line-height: 1.2 (swityicons.css:19); on a flex box that leaves
     the glyph riding above centre, same as the resident chevron */
  line-height: 1;
  transition: all 0.3s ease;
}

.page-fq .new-section.faq-section .faq-item.open .chevron-type-1 {
  background-color: #9f662d;
  color: #ffffff;
}

.page-fq .new-section.faq-section .faq-answer {
  padding: 0 38px 32px;
}

.page-fq .new-section.faq-section .faq-answer.text-color-light p {
  margin: 0 0 11px;
  color: #502c1e;
  font-weight: 300;
  line-height: 1.5;
}

.page-fq .new-section.faq-section .faq-answer.text-color-light p:last-child {
  margin-bottom: 0;
}

.page-fq .new-section.faq-section .no-faq-msg {
  margin-top: 40px;
  color: rgba(80, 44, 30, 0.7);
}
/* ============================================================
   SECTION: FAQ PAGE — END
   ============================================================ */

/* ============================================================
   SECTION: BLOG PAGES — START
   blog.html (#blog listing) and blog-single.html (#blog-post), designed to
   live-html-css-lvl29/blog.html and blog-single.html.

   Both pages are LIGHT and share the hero band with faq/resources/resident —
   see SECTION: LIGHT INNER PAGES above, whose selector lists include .page-bl
   and .page-bs. The difference from those three: the blog markup declares
   bg-light / text-color-dark itself, so nothing here has to out-rank a dynamic
   class. Only the two title-alignment rules below are page-specific, because
   v1 centres the blog banner titles (.blog-banner h1.inner-page-title and
   .blog-single-banner .banner-title, live style.css:1608-1612) where the FAQ
   banner sets its title left.

   What component-common.css already owns — DO NOT restate:
     :2679-2690  .blog-grid `display: grid` and .blog-card's flex column,
                 border-radius and overflow.
     :2692-2712  .pagination and its .active state (markup commented out).
     :2714-2720  .blog-readmore's inline-block and margins.
     :2724-2734  the 75/25 article/sidebar split and their 30px gap.
     :2741-2772  the meta row, its divider, .blog-date / .blog-time and the
                 clock glyph's optical nudge.
     :2774-2779  the post's 530px hero image.
     :2802-2840  the related grid, card, 315px thumb and the .related-badge.
     :2842-2878  the sidebar search bar and .blg-cat.
     :2880-2894  the featured list's single-column override.
     :3335-3392  1024 responsive; :4090-4103 768, where the framework hides
                 .sidebar and .related outright and drops the grid to 1 column.

   Three gaps in the framework that had to be filled:
     1. .blog-grid gets `display: grid` but grid-template-columns ONLY inside
        media queries — 2-col at 1024 (:3367) and 1-col at 768 (:4099). Above
        1024 it is a single column, and there is no `gap` at any width. The
        desktop track is set below off the component's own grid-columns
        attribute, so it follows what the backend emits rather than a hardcoded
        3.
     2. `.italic h4` shares a rule with `.related-title` that carries
        `padding-top: 140px` (:2781-2789). On the section heading that is the
        intended breathing room; on the sidebar's "Blog Categories" and
        "Featured" headings it opens a 140px hole. The markup already asks for
        pt-0 but `.pt-0` (0,1,0) loses to `.new-section.blog-post .italic h4`
        (0,3,0), so it is re-asserted here at matching specificity.
     3. .intro-type-1 carries `padding-top: 180px` (style.css:1602) because on
        amenities/gallery the hero is a backdrop the intro sits over. Here the
        hero is a band, so the markup's pt-50 is what is wanted — and `.pt-50`
        (0,1,0) also loses to `.intro-type-1` (0,1,0, but later in the file).
   ============================================================ */

/* v1 centres both blog banner titles, unlike the FAQ family's left-set title */
.page-bl .inner-hero-section .inner-hero-content,
.page-bs .inner-hero-section .inner-hero-content {
  text-align: center;
}

/* the single-post title runs long, so it needs a measure rather than the full
   container width */
.page-bs .inner-hero-section .text-wrap {
  max-width: 1000px;
  margin: 0 auto;
}

/* gap 3 — the hero is a band on this page, so the intro's backdrop-era top
   padding is dropped back to what the markup's pt-50 / pb-0 asks for */
.page-bl .intro-type-1 {
  padding-top: 50px;
  padding-bottom: 0;
}

.page-bl .intro-type-1 .intro-heading .section-title {
  margin-bottom: 12px;
}

/* ----- listing grid ----- */

/* gap 1 — the component declares its column count as an attribute and nothing
   reads it; this does. Written for the three counts the backend emits. */
.page-bl .new-section.blog[grid-columns="2"] .blog-grid {
  grid-template-columns: repeat(2, 1fr);
}

.page-bl .new-section.blog[grid-columns="3"] .blog-grid {
  grid-template-columns: repeat(3, 1fr);
}

.page-bl .new-section.blog[grid-columns="4"] .blog-grid {
  grid-template-columns: repeat(4, 1fr);
}

/* and a fallback, so a missing or unexpected attribute still lays out */
.page-bl .new-section.blog .blog-grid {
  gap: 30px;
}

/* v1's card: .blog-post-grid .alm-reveal li.single-post (live style.css:1556) */
.page-bl .new-section.blog .blog-card {
  padding: 20px;
  border: 1px solid #e3e3e3;
  border-radius: 15px;
  background-color: #ffffff;
  transition: box-shadow 0.3s ease, transform 0.3s ease;
}

.page-bl .new-section.blog .blog-card:hover {
  box-shadow: 0 5px 16px 0 #080f340f;
  transform: translateY(-4px);
}

.page-bl .new-section.blog .blog-card-shadow {
  display: flex;
  flex-flow: column;
  height: 100%;
}

/* v1: 300px cover thumb with an 8px radius */
.page-bl .new-section.blog .blog-thumb img {
  display: block;
  width: 100%;
  height: 300px;
  border-radius: 8px;
  object-fit: cover;
}

/* the "no featured image" card variant ships an empty div instead of an <img> */
.page-bl .new-section.blog .blog-img-block {
  width: 100%;
  height: 300px;
  border-radius: 8px;
  background-color: #f1efea;
}

.page-bl .new-section.blog .blog-content {
  display: flex;
  flex: 1 1 auto;
  flex-flow: column;
}

/* v1: .single-post .single-post-title { margin: 25px 0 } */
.page-bl .new-section.blog .blog-title {
  margin: 25px 0 0;
  font-size: 1.222rem;
  font-weight: 700;
  line-height: 1.4;
}

.page-bl .new-section.blog .blog-title a {
  color: #502c1e;
  text-decoration: none;
  transition: color 0.3s ease;
}

.page-bl .new-section.blog .blog-title a:hover {
  color: #9f662d;
}

/* v1: .post-date is #4e4e4e 500, span.post-cat is #989898 with a rule between
   them — here the component supplies a real .blog-divider span instead of the
   :after pseudo v1 draws */
.page-bl .new-section.blog .blog-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 14px;
  font-size: 0.778rem;
  font-weight: 500;
}

.page-bl .new-section.blog .blog-date {
  color: #4e4e4e;
}

.page-bl .new-section.blog .blog-divider {
  color: #dedede;
}

.page-bl .new-section.blog .blog-category a {
  color: #989898;
  text-decoration: none;
}

/* v1: .single-post-excerpt { margin-top: 16px; color: #363636 } */
.page-bl .new-section.blog .blog-desc {
  flex: 1 1 auto;
  margin: 16px 0 0;
  color: #363636;
  font-weight: 300;
  line-height: 1.6;
}

/* v1 hides the card read-more and lets the image and title carry the link.
   Kept here instead — the component ships it and a visible affordance is
   worth having — but styled as v1's uppercase READ MORE from the sidebar. */
.page-bl .new-section.blog .blog-readmore {
  align-self: flex-start;
  margin: 18px 0 0;
  padding-bottom: 4px;
  border-bottom: 1px solid #9f662d;
  font-size: 0.778rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition: all 0.3s ease;
}

.page-bl .new-section.blog .blog-readmore:hover {
  border-bottom-color: #502c1e;
  color: #502c1e;
}

.page-bl .new-section.blog .no-blogs {
  margin-top: 40px;
  color: rgba(80, 44, 30, 0.7);
  font-style: italic;
  text-align: center;
}

/* ----- single post ----- */

.page-bs .new-section.blog-post .main-content {
  color: #363636;
}

.page-bs .new-section.blog-post .blog-date,
.page-bs .new-section.blog-post .blog-time {
  color: #4e4e4e;
}

.page-bs .new-section.blog-post .blog-meta .blog-divider {
  color: #dedede;
}

.page-bs .new-section.blog-post .main-content > .blog-category {
  color: #989898;
}

.page-bs .new-section.blog-post .main-content img {
  border-radius: 8px;
}

/* v1: .single-post-body .post-content h2, h3 { margin: 25px 0 20px } */
.page-bs .new-section.blog-post .main-content h2 {
  margin: 32px 0 16px;
  color: #502c1e;
  font-size: 1.556rem;
  font-weight: 700;
  line-height: 1.35;
}

.page-bs .new-section.blog-post .main-content p {
  margin: 0 0 18px;
  font-weight: 300;
  line-height: 1.8;
}

.page-bs .new-section.blog-post .main-content a {
  color: #9f662d;
  text-decoration: underline;
}

/* v1: h2.widget-title — a ruled heading over each sidebar block */
.page-bs .new-section.blog-post .related-title {
  color: #502c1e;
  border-bottom-color: #dedede;
}

/* gap 2 — the sidebar headings share .related-title's 140px top padding */
.page-bs .new-section.blog-post .italic h4.pt-0 {
  padding-top: 0;
  color: #502c1e;
  border-bottom-color: #dedede;
}

.page-bs .new-section.blog-post .sidebar .search-bar {
  border-color: #e3e3e3;
  border-radius: 8px;
}

.page-bs .new-section.blog-post .sidebar .search-bar input {
  color: #502c1e;
}

.page-bs .new-section.blog-post .sidebar .search-bar input::placeholder {
  color: rgba(80, 44, 30, 0.5);
  opacity: 1;
}

/* the component pointed .search-icon at a WordPress plugin SVG; the markup now
   carries a swi-search glyph, which needs the anchor to be a flex box rather
   than the 20x20 image slot the framework sizes (:2864-2869) */
.page-bs .new-section.blog-post .search-bar a.search-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #9f662d;
  font-size: 0.889rem;
  line-height: 1;
}

.page-bs .new-section.blog-post .blg-cat {
  color: #4e4e4e;
}

/* v1: .single-related-posts — bordered, 15px radius, 8px thumb */
.page-bs .new-section.blog-post .related-card {
  border-color: #e3e3e3;
  border-radius: 15px;
  overflow: hidden;
  background-color: #ffffff;
  transition: box-shadow 0.3s ease, transform 0.3s ease;
}

.page-bs .new-section.blog-post .related-card:hover {
  box-shadow: 0 5px 16px 0 #080f340f;
  transform: translateY(-4px);
}

.page-bs .new-section.blog-post .related-badge {
  color: #502c1e;
  box-shadow: 0 5px 16px 0 #080f340f;
}

.page-bs .new-section.blog-post .related-card h4 a {
  color: #502c1e;
  text-decoration: none;
  line-height: 1.45;
  transition: color 0.3s ease;
}

.page-bs .new-section.blog-post .related-card h4 a:hover {
  color: #9f662d;
}

/* the featured list in the sidebar runs at a smaller measure than the
   three-across grid below the article */
.page-bs .new-section.blog-post .featured .related-card img {
  height: 180px;
}

.page-bs .new-section.blog-post .featured .related-card h4 {
  font-size: 1rem;
}
/* ============================================================
   SECTION: BLOG PAGES — END
   ============================================================ */



/* ============================================================
   SECTION: FLOORPLAN FILTERS + FLOOR PICKER — START
   Ported from live-html-css-lvl29. Hero-style band with a photo
   background and a dark diagonal gradient: intro copy on the left, the
   building render with its 29-floor clickable SVG overlay, and the select
   filters. Floors are invisible until hover/active, then fill bronze.
   ============================================================ */
.special-floorplan-filters {
  position: relative;
  display: flex;
  flex-flow: wrap;
  padding: 135px 70px 0;
  background-size: cover;
  background-position: center center;
}

.custom-filters-gradient {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(
    130deg,
    rgba(56, 47, 45, 0.75),
    rgba(0, 0, 0, 0.9) 80%
  );
}

.flp-image-container {
  position: relative;
  width: 60%;
}

.flp-intro {
  position: absolute;
  top: 0;
  left: 0;
  width: 64%;
}

.flp-intro h2.section-heading {
  margin: -10px 0 20px;
}

/* --- Building render + floor picker overlay --- */
.special-floor-picker {
  position: relative;
  width: 56.66%;
  margin-left: 43.33%;
}

.special-floor-picker .property-sitemap-img {
  display: block;
  width: 100%;
  height: auto;
}

.special-floor-picker svg#floors {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.special-floor-picker svg#floors g.floor {
  cursor: pointer;
}

.special-floor-picker svg#floors g.floor path {
  opacity: 0;
  fill: #9f662d;
}

.special-floor-picker svg#floors g.floor:hover path,
.special-floor-picker svg#floors g.floor.active path {
  opacity: 0.6;
}

.special-floor-picker svg#floors g.floor text {
  fill: #ffffff;
  font-weight: 100;
  opacity: 0.5;
}

.special-floor-picker svg#floors g.floor:hover text,
.special-floor-picker svg#floors g.floor.active text {
  opacity: 1;
}

/* --- Select filters --- */
.flp-filter-container {
  position: relative;
  width: 40%;
  padding: 10px;
  font-size: 0;
}

.flp-filter-container .filter-box {
  display: inline-block;
  vertical-align: top;
  width: calc(50% - 12px);
  margin: 15px 6px;
  border-bottom: 2px solid;
  font-size: 0.778rem;
  font-weight: 500;
}

.flp-filter-container .filter-box .nice-select {
  width: 100%;
  padding: 8px;
  background-color: transparent;
  border: none;
  float: none;
  line-height: 26px;
  font-weight: 700;
  text-transform: uppercase;
  color: #000000;
}

.flp-filter-container .filter-box .nice-select > span {
  color: #ffffff;
}

.flp-filter-container .filter-box .nice-select ul.list {
  width: 100%;
  max-height: 440px;
  overflow: auto;
}

/* ===== Move-in-date filter — START =====
   The date field is a bare <input>, so without this it renders as a white
   browser textbox next to five transparent underlined selects. v1 strips it
   back to match (v1 style.css .flp-date-selector). The placeholder inherits
   its colour from the text-color-light class already on the input rather
   than hardcoding #fff, so the backend can still re-theme it. */
.flp-filter-container .filter-box .flp-date-selector {
  width: 100%;
  padding: 0 10px;
  /* inputs do not inherit type styling, so the label would sit a couple of
     px smaller than the five nice-select labels beside it */
  font-family: inherit;
  font-size: inherit;
  background: transparent;
  border: none;
  line-height: 42px;
  font-weight: 700;
  text-transform: uppercase;
}

.flp-filter-container .filter-box .flp-date-selector::placeholder {
  color: inherit;
  opacity: 1;
}
/* ===== Move-in-date filter — END ===== */

/* --- View selector tabs --- */
/* ===== View selector tabs — START =====
   The tab sits on the beige ground between the filter hero and the first
   plan row and needs breathing room on both sides, or it reads as part of
   the listing. */
.flp-views {
  padding: 60px 0 40px;
  text-align: center;
}

.flp-views .view-selectors {
  margin: 0;
  padding: 0;
  list-style: none;
}
/* ===== View selector tabs — END ===== */

li.view-selector {
  display: inline-block;
  vertical-align: middle;
  margin: 0 1px;
  padding: 12px 25px;
  line-height: 1;
  cursor: pointer;
}
/* ============================================================
   SECTION: FLOORPLAN FILTERS + FLOOR PICKER — END
   ============================================================ */

/* ============================================================
   SECTION: FLOORPLAN LISTING — START
   Matches live-html-css-lvl29's floorplans listing: each plan is one
   full-width ROW on a beige ground, split into five 20% columns divided by
   2px rules — image | title | bed/bath+sqft | price/availability | button.
   This markup ships the same pieces as a stacked card, so the card is
   turned back into a row here and the parts are reordered with flex.
   component-common.css's .new-section.floorplan-page card rules are
   overridden where they conflict.
   ============================================================ */
/* The beige ground comes from bg-accent on the wrapper in the markup and the
   card's white from bg-light, so both stay backend-controllable.

   IMPORTANT: every selector below is written .new-section.floorplan-page — the
   same three-class shape component-common.css uses for its stacked-card rules.
   style.css loads last, so equal specificity means these win. Written as plain
   .floorplan-page they LOSE, the framework's repeat(4, 1fr) grid and
   flex-direction: column card take back over, and each row collapses into
   five ~70px columns that wrap one word per line. */
.new-section.floorplan-page .card-container {
  padding-top: 40px;
  /* NOTE: this padding is also what stops the last .flp-row bottom margin
     collapsing out through the section. Take it to 0 and the margin escapes,
     pushing the footer down over 80px of white body background. */
  padding-bottom: 80px;
}

/* one plan = one full-width row, overriding the framework's 4-up grid */
.new-section.floorplan-page .flp-row {
  display: flex;
  flex-flow: column;
  /* no gap: the alternating bands have to meet edge to edge, or the beige
     ground shows through between them and every row looks striped */
  gap: 0;
  /* the space under the list belongs to .card-container padding; as a margin
     here it collapses out of the section instead */
  margin-bottom: 0;
}

/* separates the available list from the "Unavailable Floor Plans" heading */
.new-section.floorplan-page .available_flp {
  margin-bottom: 60px;
}

/* ===== Alternating row bands — START =====
   Odd rows are the white card, even rows fall through to the section own
   bg-accent ground. Done with :nth-child rather than the .odd/.even classes
   in the markup because the backend emits the same parity class on every
   row, so those cannot be relied on. No colour is named here: the white
   still comes from bg-light on the card, and the beige from the section, so
   both stay backend-controllable. */
.new-section.floorplan-page .flp-row > .single-floorplan:nth-child(even) .flp-card {
  background-color: transparent;
}
/* ===== Alternating row bands — END ===== */

/* ===== Five-row scroll cap — START =====
   Past five plans the list scrolls inside itself instead of pushing the
   footer off the page. --flp-row-h is one row: 140px of plan image plus the
   card 20px top and bottom padding. With five or fewer rows the content is
   shorter than the cap, so no scrollbar appears at all. */
.new-section.floorplan-page .flp-row {
  --flp-row-h: 180px;
  max-height: calc(var(--flp-row-h) * 5);
  overflow-y: auto;
}

.new-section.floorplan-page .flp-row::-webkit-scrollbar {
  width: 6px;
}

.new-section.floorplan-page .flp-row::-webkit-scrollbar-thumb {
  background-color: rgba(0, 0, 0, 0.25);
  border-radius: 3px;
}
/* ===== Five-row scroll cap — END ===== */

.new-section.floorplan-page .single-floorplan {
  width: 100%;
  padding: 0;
}

/* the card is the row itself, so it must be laid out across, not down */
.new-section.floorplan-page .flp-card {
  position: relative;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: stretch;
  height: auto;
  padding: 20px;
}

/* --- 1. Image column (DOM order 2, pulled first) --- */
.new-section.floorplan-page .flp-card-body {
  order: 1;
  flex: 0 0 18%;
  max-width: 18%;
  height: 140px;
  padding: 0;
  border-right: 2px solid rgba(0, 0, 0, 0.1);
}

.new-section.floorplan-page .flp-card-body .card-img-wrap {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
}

.new-section.floorplan-page .flp-card-body .flp-single-page-img-blk {
  display: block;
  width: 100%;
  height: 100%;
}

/* plans are line art — contain, never crop */
.new-section.floorplan-page .flp-card-body img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* The framework leaves the offer badge in normal flow, where it would stack
   above the plan and eat the fixed row height. Float it over the image. */
.new-section.floorplan-page .flp-discount-wrap {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  max-width: 100%;
}
.new-section.floorplan-page .flp-discount-wrap .discount-on {
      display: flex;
    gap: 6px;
    align-items: center;
}

.new-section.floorplan-page .discount-on {
  min-height: 0;
  padding: 4px 8px;
  font-size: 0.611rem;
  line-height: 1.2;
}

/* --- 2 + 3. Title and bed/bath columns --- */
.new-section.floorplan-page .flp-card-header {
  order: 2;
  flex: 0 0 42%;
  max-width: 42%;
  align-items: stretch;
  gap: 0;
  padding: 0;
}

/* .flp-details is nested INSIDE .flp-title-wrap in the Swifty markup, not a
   sibling of it, so the title/bed-bath split has to happen one level down —
   title-wrap is the two-column container, not itself a column. */
.new-section.floorplan-page .flp-card-header .flp-title-wrap {
  display: flex;
  flex-flow: row;
  align-items: stretch;
  width: 100%;
  max-width: 100%;
  padding: 0;
}

.new-section.floorplan-page .flp-card-header .flp-title-wrap > .flp-more-details {
  display: flex;
  flex-flow: column;
  justify-content: center;
  width: 50%;
  padding: 0 30px;
}

/* v1: .flp-primary-info h2 { font-size: 30px } */
.new-section.floorplan-page .flp-card-header .flp-title {
  margin: 0;
  font-family: "Playfair Display", Georgia, serif;
  font-size: 2.143rem;
  line-height: 1.2;
}

.new-section.floorplan-page .flp-card-header .flp-details {
  display: flex;
  flex-flow: column;
  justify-content: center;
  width: 50%;
  padding: 0 30px;
  font-weight: 300;
  border-left: 2px solid rgba(0, 0, 0, 0.1);
}

/* the status dot must hold the first line when the date wraps to two */
.new-section.floorplan-page .availability-dot {
  align-items: flex-start;
}

.new-section.floorplan-page .availability-dot::before {
  flex: 0 0 8px;
  margin-top: 0.45em;
}

/* The 360 and favourite icons have no column of their own in a five-column
   row, so they sit over the foot of the plan image instead. */
.new-section.floorplan-page .flp-icon-wrap {
  position: absolute;
  bottom: 20px;
  left: 20px;
  z-index: 3;
  gap: 10px;
}

/* --- 4 + 5. Price/availability and button --- */
.new-section.floorplan-page .flp-card-footer {
  order: 3;
  flex: 0 0 40%;
  max-width: 40%;
  flex-wrap: nowrap;
  align-items: stretch;
  padding: 0;
}

.new-section.floorplan-page .flp-card-footer .flp-card-meta {
  display: flex;
  flex-flow: column;
  justify-content: center;
  width: 58%;
  padding: 0 30px;
  border-left: 2px solid rgba(0, 0, 0, 0.1);
  border-right: 2px solid rgba(0, 0, 0, 0.1);
}

.new-section.floorplan-page .flp-card-footer .flp-text-wrap {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.new-section.floorplan-page .flp-card-footer .flp-disc-price {
  font-weight: 700;
}

.new-section.floorplan-page .flp-card-footer p {
  margin: 5px 0;
  font-weight: 300;
}

.new-section.floorplan-page .flp-btn-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42%;
  padding: 0 20px;
}

/* v1: a.flp-leasing-btn — solid button with a soft drop shadow */
.new-section.floorplan-page .flp-btn-wrap .flp-next-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  font-weight: 700;
  box-shadow: 5px 5px 10px 2px rgba(0, 0, 0, 0.2);
  transition: all 0.3s ease;
}

.new-section.floorplan-page .flp-btn-wrap .flp-next-btn:hover {
  opacity: 0.7;
}
/* ============================================================
   SECTION: FLOORPLAN LISTING — END
   ============================================================ */

/* ============================================================
   SECTION: FLOORPLAN FILTER — START
   The filter bar on floorplan.html. Structure, the dropdown buttons and
   the card grid come from component-common.css's .new-section.floorplan-page
   rules — the wrapper carries both classes so those apply. Everything below
   is the v2 theme layer for the parts that file does not define: the open
   panel, clear button, active-filter chips, histogram, range slider and
   datepicker shells.
   ============================================================ */
.floorplan-page .filter-container {
  padding: 30px 0;
}

.floorplan-page .floorplan-filter-filters {
  display: flex;
  flex-flow: wrap;
  align-items: center;
  gap: 12px;
}

.floorplan-page .flp-button-group {
  display: flex;
  flex-flow: wrap;
  align-items: center;
  gap: 12px;
}

/* --- Dropdown shell --- */
.floorplan-page .flp-dropdown {
  position: relative;
}

.floorplan-page .flp-dropdown-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 40px 12px 18px;
  border: 1px solid transparent;
  border-radius: 2px;
  font-weight: 500;
  letter-spacing: 0.5px;
  cursor: pointer;
  transition: all 0.3s ease;
}

/* caret */
.floorplan-page .flp-dropdown-btn::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 16px;
  width: 7px;
  height: 7px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-70%) rotate(45deg);
  transition: transform 0.3s ease;
}

.floorplan-page .flp-dropdown.open .flp-dropdown-btn::after {
  transform: translateY(-30%) rotate(-135deg);
}

.floorplan-page .flp-filter-icon {
  display: inline-flex;
  align-items: center;
  margin-right: 6px;
}

/* --- Open panel --- */
.floorplan-page .flp-dropdown-content {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 20;
  min-width: 280px;
  padding: 20px;
  background: #ffffff;
  border: 1px solid rgba(80, 44, 30, 0.15);
  border-radius: 2px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.18);
}

.floorplan-page .flp-dropdown.open .flp-dropdown-content {
  display: block;
}

.floorplan-page .flp-dropdown-content label {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  color: #502c1e;
  cursor: pointer;
}

.floorplan-page .flp-dropdown-content input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: #9f662d;
}

/* --- Clear --- */
.floorplan-page .flp-clear-btn {
  display: inline-block;
  margin-top: 14px;
  padding: 0;
  background: none;
  border: 0;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  text-decoration: underline;
  color: #9f662d;
  cursor: pointer;
}

/* --- Active filter chips --- */
.floorplan-page .selected-filters-container,
.floorplan-page .active-filters {
  display: flex;
  flex-flow: wrap;
  gap: 8px;
}

.floorplan-page .selected-filters-container:empty,
.floorplan-page .active-filters:empty {
  display: none;
}

.floorplan-page .selected-filters-container > *,
.floorplan-page .active-filters > * {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border: 1px solid #9f662d;
  border-radius: 30px;
  font-size: 0.778rem;
  color: #9f662d;
}

/* --- Histogram behind the sliders --- */
.floorplan-page .histogram-container {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 60px;
  margin-bottom: 10px;
}

.floorplan-page .histogram-container > * {
  flex: 1 1 auto;
  background: rgba(159, 102, 45, 0.25);
}

.floorplan-page .histogram-container > .in-range {
  background: #9f662d;
}

/* --- Range slider shell (the library draws the handles) --- */
.floorplan-page .slider-container {
  position: relative;
  height: 4px;
  margin: 18px 6px;
  background: rgba(80, 44, 30, 0.2);
  border-radius: 2px;
}

.floorplan-page .slider-range-output {
  display: flex;
  justify-content: space-between;
  margin-top: 14px;
  font-weight: 600;
  color: #502c1e;
}

/* --- Datepicker shell --- */
.floorplan-page .datepicker-container {
  min-width: 260px;
}

/* --- Favourites toggle --- */
.floorplan-page .swifty-favorite-filter-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 18px;
  border: 1px solid transparent;
  border-radius: 2px;
  cursor: pointer;
}

.floorplan-page .swifty-favorite-filter-btn[hidden] {
  display: none;
}
/* ============================================================
   SECTION: FLOORPLAN FILTER — END
   ============================================================ */

/* ============================================================
   SECTION: CONTACT PAGE — START
   The contact page runs three components on the dark inner-page wrapper: the
   inner hero (hidden here), the Swifty form section, and the contact-info +
   map panel.

   component-common.css already does the heavy lifting and is NOT repeated:
     - the whole form system at :935-1160 — field geometry, .form-row flex with
       gap:24px, .option-group, .g-checkbox, .time-range-inputs, and fully
       custom radio/checkbox controls drawn with border:2px solid +
       color:currentColor (which inherit white here, so they are left alone);
     - the form's responsive work at :3119-3140 (1024) and :3401-3470 (768);
     - the .contact-map internals at :2306-2373 — .info-section grid,
       .hours-list rows, icons, .section-title.

   Everything below is either colour (the framework assumes a LIGHT ground and
   this page is black) or the few things the framework genuinely omits.
   ============================================================ */

/* The hero component is shipped in the markup so the backend can still
   generate it; v1's contact page has no hero photo, so it is switched off
   here. Deleting this rule is all it takes to turn it back on. */
.page-ct .contact-inner-hero {
  display: none;
}

/* --- Form: desktop column split ---
   component-common.css sizes #form-section .col.left-col / .right-col ONLY
   inside its 1024 (:3119, 50%) and 768 (:3401, 100%) blocks, and the bare .col
   class has no width of its own (component-main.css only defines .col-1..12).
   Above 1024 both columns are therefore unsized flex children. This is the
   desktop split; the framework's !important rules take over below 1024. */
.page-ct #form-section .d-flex.w-100 {
  gap: 60px;
  align-items: flex-start;
}

.page-ct #form-section .col.left-col {
  width: 55%;
}

.page-ct #form-section .col.right-col {
  width: 45%;
}

/* the framework gives .image-section height:100% and the img object-fit:cover,
   but nothing establishes a height to fill on this page */
.page-ct #form-section .image-section {
  min-height: 100%;
  aspect-ratio: 3 / 4;
}

/* --- Form: colour only, geometry belongs to the framework --- */

/* v1: .formmangr-field input — dark fill so the fields read on black.
   The framework sets only border/padding/radius and leaves the background to
   the browser default (white), which is its light-ground assumption. */
.page-ct .form-section input[type="text"],
.page-ct .form-section input[type="email"],
.page-ct .form-section input[type="date"],
.page-ct .form-section input[type="tel"],
.page-ct .form-section select,
.page-ct .form-section textarea {
  border-color: rgba(226, 222, 213, 0.4);
  background-color: rgba(0, 0, 0, 0.7);
  color: #ffffff;
}

/* The framework's placeholder colour is #494949 — chosen for white fields and
   unreadable on these. It declares all three vendor forms, so both of the ones
   that still matter are restated. */
.page-ct .form-section input::placeholder,
.page-ct .form-section textarea::placeholder {
  color: rgba(255, 255, 255, 0.65);
  opacity: 1;
}

.page-ct .form-section input::-webkit-input-placeholder,
.page-ct .form-section textarea::-webkit-input-placeholder {
  color: rgba(255, 255, 255, 0.65);
  opacity: 1;
}

/* select:invalid is how the framework greys the unchosen placeholder option */
.page-ct .form-section select:invalid {
  color: rgba(255, 255, 255, 0.65);
}

/* The framework sets appearance:none on the select but supplies no arrow, so
   the control loses its affordance entirely.

   It must be a single background-image, not the usual two-gradient chevron:
   component-common.css:3023-3028 forces `background-size: 20px 20px` and
   `background-position: 98% center` on EVERY select with !important (its own
   background-image line is commented out). A pair of gradients gets crushed
   into that one 20px box and renders as a white blob. An SVG data URI drawn to
   suit 20x20 works with that forced sizing instead of fighting it — do not add
   background-size/position here, they cannot win. */
.page-ct .form-section select {
  padding-right: 48px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}

/* The default focus ring is low contrast against a dark fill. */
.page-ct .form-section input:focus,
.page-ct .form-section select:focus,
.page-ct .form-section textarea:focus {
  outline: 2px solid #9f662d;
  outline-offset: 2px;
}

/* #form-section .error is `red`, which is unreadable on black */
.page-ct #form-section .error {
  color: #ff8a80;
}

/* component-common.css:985 sets `padding: 16px 0` on this button — no
   horizontal padding at all, so the label sits flush against both edges. */
.page-ct #form-section .form-section-wrapper button.btn {
  padding: 16px 40px;
  min-width: 170px;
}

.page-ct .form-section small.recaptcha-declaration {
  display: block;
  margin-bottom: 15px;
  font-size: 0.722rem;
  color: rgba(255, 255, 255, 0.6);
}

.page-ct .form-section small.recaptcha-declaration a {
  color: rgba(255, 255, 255, 0.85);
  text-decoration: underline;
}

/* --- Contact info + map panel --- */

/* component-common.css only sizes these two inside its max-width:1440 block,
   so above 1440 they are unsized flex children. This is the desktop split. */
.page-ct .contact-map .container.d-flex {
  gap: 40px;
  align-items: flex-start;
}

.page-ct .contact-map .contact-info {
  width: 35%;
}

.page-ct .contact-map .map-area {
  width: 65%;
}

/* the framework only zeroes the LAST info-section's margin; the others have none */
.page-ct .contact-map .info-section {
  margin-bottom: 30px;
}

.page-ct .contact-map .section-title {
  font-weight: 700;
  letter-spacing: 0.1em;
}

.page-ct .contact-map .hours-list .day,
.page-ct .contact-map .hours-list .time {
  font-weight: 300;
}

.page-ct .contact-map .contact-directions-link,
.page-ct .contact-map a.phone {
  color: inherit;
  text-decoration: none;
}

.page-ct .contact-map .contact-directions-link:hover,
.page-ct .contact-map a.phone:hover {
  color: #9f662d;
}

/* v1: .google-map.tour-map */
.page-ct #footer-google-map {
  height: 30vw;
  min-height: 400px;
}

.page-ct #footer-google-map iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}
/* ============================================================
   SECTION: CONTACT PAGE — END
   ============================================================ */

/* ============================================================
   SECTION: FOOTER — START
   Behaviour ported from the plugin's own footer-3.css (collective),
   which is the stacked LAYOUT B this markup uses:
     swifty-frontend/components/footer/css/footer-3.css
   Every band is width:100% and centred with flex + gap, and the lower
   bar uses margin-left:auto rather than fixed widths — so switching any
   block off just closes the gap and the footer collapses to the live
   LVL29 look. Colours are re-themed here for the dark photo ground
   (footer-3 is built for a light footer).
   Structural rules already in component-common.css are not restated.
   ============================================================ */
.footer {
  position: relative;
  flex-flow: wrap;
  overflow: hidden;
}

/* --- Photo background + overlay (live LVL29 treatment) --- */
.footer .footer-bg-wrap {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 0;
}

.footer .footer-bg-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}

.footer .footer-bg-overlay {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

/* --- Bands --- */
.footer .footer-top-wraper,
.footer .footer-lower {
  position: relative;
  z-index: 1;
  width: 100%;
}

.footer .footer-top-wraper {
  display: flex;
  flex-flow: wrap;
  padding: 0 2.778rem;
  flex-direction: column;
}

/* --- Logo (not in footer-3; live LVL29 has one) --- */
.footer .footer-logo {
  order: 0;
  width: 100%;
  padding-top: 2.778rem;
  text-align: center;
}

/* component-main.css sets `img { display: block }`. A block image inside an
   inline <a> ignores text-align:center on the wrapper, so the anchor is made
   inline-flex to shrink-wrap the image — then the centring applies. */
.footer .footer-logo a {
  display: inline-flex;
}

.footer .footer-logo .logo-img {
  width: 205px;
  height: auto;
}

/* --- Social --- */
.footer .footer-social {
  order: 1;
  width: 100%;
  padding-top: 2.222rem;
  padding-bottom: 2.222rem;
}

.footer .social-links {
  display: flex;
  justify-content: center;
  gap: 12px;
}

.footer ul.social-links li.social-icon a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 47px;
  height: 47px;
  border: 1px solid;
  border-radius: 50%; /* live LVL29 is round; footer-3 squares these off */
  font-size: 1.1rem;
  transition: all 0.3s ease;
}

/* --- Menu: centred row, hairline above and below (footer-3 behaviour) --- */
.footer .footer-menu-wraper {
  position: relative;
  order: 2;
  display: flex;
  justify-content: center;
  align-items: self-start;
  gap: 2.111rem;
  padding-top: 2.778rem;
  padding-bottom: 2.778rem;
}

.footer .footer-menu {
  justify-content: center;
  flex-flow: wrap;
  gap: 2rem;
}

.footer .footer-menu .footer-menu-item {
  text-align: center;
}

/* --- Two-list menu (footer-3 behaviour) ---
   The backend splits the footer menu into two <ul>s: .submenu-wrap holds
   items that have children, .no-submenu-wrap holds the flat ones. The
   submenu column is divided from the rest by a rule on its right, and the
   flat items lay out as a column-flow grid, 4 rows deep. If only one list
   is output, the other simply is not rendered and this still works. */
.footer .footer-menu.submenu-wrap {
  border-right: 1px solid rgba(255, 255, 255, 0.18);
  padding-right: 36px;
}

.footer .footer-menu.no-submenu-wrap {
  display: grid !important;
  grid-auto-flow: column;
  grid-template-rows: repeat(4, auto);
  gap: 1.111rem;
}

/* a lone .submenu-wrap has nothing to divide from */
.footer .footer-menu.submenu-wrap:not(:has(+ .footer-menu.no-submenu-wrap)) {
  border-right: 0;
  padding-right: 0;
}

.footer .footer-submenu {
  display: flex;
  flex-direction: column;
  gap: 15px;
  margin-top: 20px;
  max-width: 170px;
  text-align: left;
}

.footer .footer-menu .footer-menu-item .menu-item-link {
  padding: 0 10px;
}

.footer .footer-menu-wraper::before,
.footer .footer-menu-wraper::after {
  content: "";
  position: absolute;
  width: 100%;
  border-bottom: 1px solid rgba(255, 255, 255, 0.18);
}

.footer .footer-menu-wraper::before {
  top: 0;
}

.footer .footer-menu-wraper::after {
  bottom: 0;
}

/* --- Contact row --- */
.footer .footer-address-wraper {
  order: 3;
  width: 100%;
  margin: 0 auto;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: flex-start;
  gap: 40px;
  padding: 39px 0;
  text-align: center;
}

.footer .footer-email-wrap a,
.footer .footer-contact-wrap a,
.footer .footer-address-wrap a,
.footer .footer-time-wrap {
  gap: 5px;
}

.footer .footer-address-wraper span.ficon-wrap {
  line-height: 1;
  font-size: 1rem;
}

.footer .footer-time-wrap .footer-time {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* --- Lower bar --- */
.footer .footer-lower {
  display: flex;
  align-items: center;
  padding: 16px 48px;
  background: rgba(0, 0, 0, 0.35);
}

.footer .footer-copyright {
  padding-right: 20px;
}

.footer .footer-policy-nav {
  padding-left: 10px;
  padding-right: 10px;
  border-left: 1px solid rgba(255, 255, 255, 0.3);
  border-right: 1px solid rgba(255, 255, 255, 0.3);
}

.footer ul.policy-nav {
  display: flex;
}

.footer ul.policy-nav li a {
  position: relative;
  padding-left: 10px;
  border-bottom: none;
}

/* small round separator between policy links */
.footer ul.policy-nav li a::after {
  content: "";
  position: absolute;
  top: 50%;
  left: -10px;
  height: 0;
  border: 2px solid rgba(255, 255, 255, 0.45);
  border-radius: 50%;
  transform: translateY(-50%);
}

.footer ul.policy-nav li:first-child a::after {
  display: none;
}

.footer .footer-property-icons {
  display: flex;
  align-items: center;
  flex-grow: 1;
  margin-right: auto;
  padding-left: 8px;
}

.footer .property-icons {
  border-right: 0;
}

.footer .cb-logo-wrap {
  margin-left: auto;
}
/* ============================================================
   SECTION: FOOTER — END
   ============================================================ */
/* ============================================================
   SECTION: HERO DOTS — START
   ============================================================ */
/* ===== Hero dots (slick-generated markup — colours cannot be class-driven) ===== */
.hero-slider .slick-dots {
  position: absolute;
  bottom: 70px;
  left: 0;
  width: 100%;
  display: flex !important;
  justify-content: center;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
  z-index: 6;
}

/* The dot is drawn on the <li>, not the <button>: component-common.css sets
   `section.hero-banner .slider-container .slick-dots>li button { display:none }`
   with a more specific selector, so anything styled on the button collapses to
   0x0 and the dots vanish. */
.hero-slider .slick-dots li {
  width: 10px;
  height: 10px;
  line-height: 0;
  border: 1px solid #9f662d;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: all 0.3s ease;
}

.hero-slider .slick-dots li.slick-active {
  background: #9f662d;
}

/* ============================================================
   SECTION: HERO DOTS — END
   ============================================================ */

/* ============================================================
   SECTION: SCROLL-TO-NEXT ARROW — START
   ============================================================ */
/* ===== Scroll-to-next arrow =====
   The white circle and its bounce come from component-common.css
   (section.hero-banner .bottom-section-link .arrow — 45x45, bounce-arrow).
   Styling .bottom-section-link here too produced a SECOND white circle around
   that one, which is why the arrow appeared twice. Only the wrapper position
   and the svg inside the circle are set here — component-common defines
   neither.

.bottom-section-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  animation: heroBounce 2s infinite;
}

@keyframes heroBounce {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(10px);
  }
}
*/

.bottom-section-link-wrapper {
  position: absolute;
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 6;
}

.bottom-section-link .arrow svg {
  display: block;
  width: 22px;
  height: 22px;
  fill: none;
  stroke: #9f662d;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ============================================================
   SECTION: SCROLL-TO-NEXT ARROW — END
   ============================================================ */

/* ============================================================
   SECTION: POLICY PAGES — START

   ONE block for all four pages built on swifty_component_policy_block():
   pet-policy.html, privacy-policy.html, terms-and-conditions.html and
   license-and-disclosure.html. Each carries .page-pl on its
   .inner-page-body-wrapper plus a page-specific hook (.page-pt / .page-pv /
   .page-tc / .page-ld), but every rule below is written against
   .policy-section: the four pages are meant to be identical, and the hooks are
   there for the one that eventually is not.

   The design is ported from v1's PET POLICY page (live-html-css-lvl29
   style.css:1249-1301): one dark ground, one 1200px measure of left-aligned
   copy, headings and lists doing all the work. No cards, no panels.

   .policy-text is an ACF WYSIWYG field, so almost everything here targets bare
   descendant tags (h4, p, ul, ol, li, a, blockquote, strong) rather than
   classes: whoever writes this copy in the editor cannot add classes. The
   exceptions are the helper classes v1's pet copy already ships inside its
   editor markup (.pet-policy-block, .pet-policy-img, .img-cont, .pet-indent,
   .pet-cta, .pet-btn), kept so the v1 content ports across unchanged.

   Type SIZES for .section-title / .section-subtitle come from typo.css; only
   colour and spacing are set here, per the v2 split.
   ============================================================ */

/* ----- the copy sits ON the photo -----
   This is the whole look of the live lvl29life.com policy pages and of v1's
   pet page: no hero band, just a photo anchored to the top of the wrapper with
   the title and the copy running over it and fading into the black.

   The base hero rule (SECTION: INNER HERO BANNER) already does that half — it
   absolutely positions .inner-hero-section as a 56vw backdrop and hides the
   component's own <h1> plate, because the block below carries the title. What
   was missing is the other half: .policy-section is in the normal flow with no
   stacking context, so the absolutely-positioned photo painted straight over
   it and the copy was a ghost behind the tree. z-index lifts it out.

   padding-top clears the fixed header and drops the title to roughly where the
   live site puts it; it has to beat the .pt-50 utility on the section, which it
   does on specificity (two classes to one). */
.page-pl .policy-section {
  position: relative;
  z-index: 5;
  padding-top: 220px;
}

/* .container already caps at 1200px and centres (component-main.css:86), so
   the wrapper only has to stop inheriting any centring of its text. */
.policy-section .text-content-wrapper {
  width: 100%;
  text-align: left;
}

/* The title and subtitle land on the brightest part of the photo — the base
   hero's fade covers the lower 60% and its vignette the edges, but the top
   third stays clean by design. A soft shadow keeps the bronze subtitle legible
   over a light frame without laying another scrim over the photograph. */
.page-pl .policy-section h2.policy-title,
.page-pl .policy-section h3.section-subtitle {
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.6);
}

.policy-section h2.policy-title {
  margin: 0 0 15px;
}

.policy-section h3.section-subtitle {
  margin: 0 0 30px;
}

/* --- The WYSIWYG body --- */
.policy-section .policy-text {
  line-height: 1.7;
  font-weight: 300;
}

.policy-section .policy-text p {
  margin: 0 0 18px;
}

.policy-section .policy-text strong {
  font-weight: 600;
}

/* v1's pet page runs h3 at 22px and h4 at 18px inside the copy
   (style.css:1255/1260). The root font-size here is 18px, so those are
   1.222rem and 1rem; h4 is the heading level the component's editor content
   actually uses, h3 is covered in case a page nests one. */
.policy-section .policy-text h3 {
  margin: 30px 0 12px;
  font-size: 1.222rem;
  font-weight: 700;
  line-height: 1.35;
}

.policy-section .policy-text h4 {
  margin: 30px 0 12px;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.02em;
}

/* the first heading sits right under the subtitle, which already has its own
   30px, so it does not need the stacking margin as well */
.policy-section .policy-text > h3:first-child,
.policy-section .policy-text > h4:first-child {
  margin-top: 0;
}

/* Lists: the framework's list resets leave these unmarked, and v1's copy leans
   on markers to separate the terms — so the markers come back here.
   ul.pet-indent is v1's own class for the same shape; it is folded in rather
   than duplicated. */
.policy-section .policy-text ul,
.policy-section .policy-text ol,
.policy-section .policy-text ul.pet-indent {
  margin: 0 0 20px;
  padding-left: 1.2em;
  line-height: 1.7;
}

.policy-section .policy-text ul,
.policy-section .policy-text ul.pet-indent {
  list-style: disc;
}

.policy-section .policy-text ol {
  list-style: decimal;
}

.policy-section .policy-text li {
  margin-bottom: 10px;
  padding: 0;
}

.policy-section .policy-text li::marker {
  color: #9f662d;
}

/* v1 underlines links in the copy in the accent tint (style.css:944).
   :not(.btn) is load-bearing, not tidiness: this selector is (0,2,1) and the
   dynamic colour classes are (0,1,0), so without it this out-ranks the
   text-color-primary on the pet CTA buttons and paints near-white text on
   their white ground. Any link carrying .btn keeps whatever the dynamic
   classes in the markup say. */
.policy-section .policy-text a:not(.btn) {
  color: #e2ded5;
  text-decoration: underline;
  transition: color 0.2s ease;
}

.policy-section .policy-text a:not(.btn):hover,
.policy-section .policy-text a:not(.btn):focus-visible {
  color: #9f662d;
}

/* A pull-quote, not a card: one bronze rule and italics, so it reads as part
   of the same column of copy. */
.policy-section .policy-text blockquote {
  margin: 28px 0;
  padding: 4px 0 4px 22px;
  border-left: 3px solid #9f662d;
  font-style: italic;
}

.policy-section .policy-text blockquote p:last-child {
  margin-bottom: 0;
}

/* --- Pet page: the floated photo and CTA row (v1 style.css:1274-1301) ---
   These live in the shared block because the markup is editor content: the
   same classes can appear on any of the four pages if someone pastes them. */
.policy-section .pet-policy-block {
  width: 100%;
  overflow: auto;
}

.policy-section img.pet-policy-img {
  float: right;
  width: 45%;
  max-width: 546px;
  height: auto;
  margin-left: 15px;
  padding: 10px;
  border: 2px solid #9f662d;
}

.policy-section .pet-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding: 1em 0;
}

/* .btn brings the framework's shape; only the sizing v1 gives it is set here,
   and the colours come from the dynamic classes in the markup. */
.policy-section a.pet-btn {
  padding: 1em 1.6em;
  font-weight: 600;
  text-decoration: none;
}

.policy-section a.pet-btn:hover {
  text-decoration: none;
}

/* ============================================================
   SECTION: POLICY PAGES — END
   ============================================================ */

/* ============================================================
   SECTION: RESPONSIVE — START
   ============================================================ */
/* =========================================================
   RESPONSIVE — one merged block per breakpoint, largest first
   ========================================================= */

/* ============================================================
   SECTION: FLOORPLAN FILTER HERO (responsive) — START
   Ports live-html-css-lvl29 floorplans.html behaviour. On a wide screen the
   intro copy is absolutely positioned beside the building render and the
   filters sit top-right; there is only room for that past ~1890px. Below it
   the intro returns to the flow above the render and the filter block is
   pulled back up over the foot of the building, exactly as v1 does.
   Breakpoint added ahead of the existing 1024 block to keep this file
   ordered largest-to-smallest.
   ============================================================ */
@media (max-width: 1890px) {
  /* No neighborhood rules needed here: the intro's left inset is already a
     percentage in the base rule, so it scales through this breakpoint. */

  /* intro leaves its absolute slot and stacks above the render */
  .special-floorplan-filters .flp-intro {
    position: relative;
    top: auto;
    left: auto;
    width: 100%;
    margin-bottom: 30px;
  }

  .special-floorplan-filters .flp-image-container {
    width: 100%;
  }

  /* the render now owns a full-width row, so the filters wrap below it —
     -220px lifts them back over its lower left, as on v1 */
  .special-floorplan-filters .flp-filter-container {
    top: -220px;
  }
}
/* ============================================================
   SECTION: FLOORPLAN FILTER HERO (responsive) — END
   ============================================================ */

/* ============================================================
   1440px, NOT 1024px — deliberate.

   component-common.css re-splits the contact panel inside its own
   `@media screen and (max-width: 1440px)` block (:3077-3091), forcing
   .contact-info to 30% and .map-area to 70% with !important. This file has no
   1440 breakpoint of its own, so without this block the range 1025-1440px is
   governed half by the framework and half by our base rules. This block exists
   purely to line up with the framework — do not merge it into 1024 below.
   ============================================================ */
@media (max-width: 1440px) {
  /* ===== CONTACT PAGE — START =====
     The framework's !important 30/70 split wins here regardless, so this only
     tightens the gutter to match it. */
  .page-ct .contact-map .container.d-flex {
    gap: 24px;
  }
  /* ===== CONTACT PAGE — END ===== */

  /* No neighborhood rule needed here any more: the copy column was narrowed to
     440px, which keeps the centred FIND US AT cue clear of the text through
     this whole range. It previously had to be pulled left to 33% because the
     wider column ran into it below ~1440. */
}

@media (max-width: 1024px) {

  /* ===== AMENITIES TABS — START =====
     The 62/38 image/copy split (SECTION: AMENITIES TABS + MASONRY) had no
     responsive step at all, so it held right down to phone widths. Eased here
     before it stacks at 767. */
  .amenities-page-gallery .amenities-container .left-col {
    width: 55%;
  }

  .amenities-page-gallery .amenities-container .right-col {
    width: 45%;
    padding-left: 30px;
  }

  /* the two decorative dot columns are pinned to 50% +/- 150px, which lands
     them on top of the copy once the layout narrows */
  .amenities-page-gallery .ct-tabs-container::before,
  .amenities-page-gallery .ct-tabs-container::after {
    display: none;
  }
  /* ===== AMENITIES TABS — END ===== */

  /* ===== APPLY NOW BUTTON — START =====
     A 115px circle crowds a tablet viewport, so it steps down before it is
     dropped entirely at 767. */
  a.apply-link {
    top: 90px;
    right: 20px;
    width: 92px;
    height: 92px;
  }

  a.apply-link.circle-cta {
    top: 80px;
  }
  /* ===== APPLY NOW BUTTON — END ===== */

  /* ===== RESOURCES PAGE — START ===== */
  .page-rs .single-resource-item {
    flex: 0 0 calc(50% - 12px);
    max-width: calc(50% - 12px);
  }
  /* ===== RESOURCES PAGE — END ===== */

  /* matches the intro-type-1 padding step on the other inner pages */
  .page-tr .vr-tour-section {
    padding-top: 150px;
  }

  /* ===== TOUR PAGE — START ===== */
  .page-tr .single-virtual-tour {
    flex: 0 0 calc(50% - 12px);
    max-width: calc(50% - 12px);
  }
  /* ===== TOUR PAGE — END ===== */
  /* ===== GALLERY PAGE — START =====
     component-common.css:3199 already forces .gallery-card to 50% with
     !important between 769 and 1024, so only the flex-basis and the video /
     tour cards need restating to match. */
  .gallery-section.new-section .gallery-card {
    flex: 0 0 calc(50% - 12px);
    max-width: calc(50% - 12px);
  }

  .gallery-section.new-section .single-virtual-tour {
    flex: 0 0 calc(50% - 12px);
    max-width: calc(50% - 12px);
  }

  .gallery-section.new-section .gallery-tabs-content::before,
  .gallery-section.new-section .gallery-tabs-content::after {
    display: none;
  }
  /* ===== GALLERY PAGE — END ===== */

  /* ===== NEIGHBORHOOD HERO + INTRO — START ===== */
  .page-nb .intro-type-1.intro-to-right .content-wrapper {
    padding: 180px 20px 60px;
  }

  /* The container narrows here while the column stays 520px, so its left edge
     marches left — the cue has to move further left or it crowds the copy.
     12%, not 26%: at the bottom of this range 26% left only 9px of gap, and
     right at the 768 boundary the copy and the cue actually overlapped. */
  .page-nb .location-content__cta {
    left: 12%;
  }
  /* ===== NEIGHBORHOOD HERO + INTRO — END ===== */

  /* ===== NEIGHBORHOOD MAP + PLACES — START =====
     v1 drops to 3 cards per view here and moves the category heading above the
     strip as a full-width, uppercase label. */
  .neighborhood.new-section .nbp-heading-wrap {
    width: 100%;
    margin-bottom: 25px;
    text-align: center;
  }

  .neighborhood.new-section .nbp-places-scroller {
    width: 100%;
  }

  .neighborhood.new-section .nbp-places-list .nb-places-ul li {
    width: 33.33%;
  }
  /* ===== NEIGHBORHOOD MAP + PLACES — END ===== */

  /* --- Header --- */
  /* --- Intro type 1: tighter padding. The photo stays a full-bleed
     backdrop at every width, as on the live site. v1 makes this change at
     767 (padding: 150px 20px 60px). --- */
  .intro-type-1 {
    padding-top: 150px;
    padding-bottom: 60px;
  }

  /* No .inner-hero-section rules needed here: the backdrop is a fluid 56vw
     band, and the intro keeps the .intro-type-1 padding set just above. */

  /* --- Footer: contact stacks to a column, lower bar wraps (footer-3's
     992 behaviour, applied at this theme's 1024 breakpoint) --- */
  .footer .footer-top-wraper {
    padding: 25px 20px;
  }

  .footer .footer-address-wraper,
  .footer .footer-email-wrap a,
  .footer .footer-contact-wrap a,
  .footer .footer-address-wrap a,
  .footer .footer-time-wrap,
  .footer .footer-time-wrap .footer-time {
    flex-direction: column;
    text-align: center;
  }

  .footer .footer-email-wrap,
  .footer .footer-contact-wrap,
  .footer .footer-address-wrap,
  .footer .footer-time-wrap {
    width: 100%;
  }

  .footer .footer-address-wraper {
    padding: 24px 0 0;
  }

  .footer .footer-lower {
    flex-flow: wrap;
    padding: 16px 20px;
  }

  .footer .footer-policy-nav {
    order: 0;
    width: 100%;
    padding-bottom: 10px;
    text-align: center;
    border: none;
  }

  .footer ul.policy-nav {
    justify-content: center;
  }

  .footer .footer-property-icons {
    width: 100%;
    justify-content: center;
    padding-left: 0;
    padding-bottom: 10px;
  }

  .footer .footer-copyright {
    order: 1;
    width: 100%;
    padding-right: 0;
    text-align: center;
  }

  .footer .attribution {
    order: 1;
    margin-left: auto;
  }

  .footer .cb-logo-wrap {
    margin: initial;
  }

  /* --- Home map: map and copy stack, box rides up less --- */
  .home-map {
    padding-bottom: 40px;
  }

  .home-map .container {
    transform: translateY(-50px);
    border-radius: 0 100px 0 0;
    padding: 40px 0;
  }

  .home-map .map-wrapper,
  .home-map .global-map-content {
    width: 100%;
  }

  .home-map .global-map-content {
    padding: 30px 30px 0;
  }

  .home-map .map-section-header {
    padding: 0 30px;
  }

  .home-map .map-contact {
    padding: 40px 30px 0;
  }

  .home-map .map-contact .address,
  .home-map .map-contact .contact {
    width: 50%;
  }

  .home-map .map-contact .address {
    padding-right: 25px;
  }

  .home-map .map-contact .contact {
    padding-left: 25px;
  }

  ._header .logo-wrapper a.logo img {
    height: 46px;
  }

  ._header .inner-header {
    min-height: 60px;
  }

  ._header .inner-header > * {
    margin-left: 8px;
    margin-right: 8px;
  }

  ._header ul.main-menu li.menu-item .menu-item-link {
    padding: 10px 8px;
  }


  /* --- Hero --- */
  .slide-flex-wrapper {
    padding-bottom: 115px;
  }

  .hero-banner.video-banner .video-container {
    bottom: 115px;
  }

  .hero-banner .btn {
    min-width: 170px;
  }

  /* --- Floorplan listing: keep the row, just tighten the gutters --- */
  .new-section.floorplan-page .flp-card-header .flp-title-wrap > .flp-more-details,
  .new-section.floorplan-page .flp-card-header .flp-details,
  .new-section.floorplan-page .flp-card-footer .flp-card-meta {
    padding: 0 15px;
  }

  .new-section.floorplan-page .flp-btn-wrap {
    padding: 0 10px;
  }

  /* ===== FLOORPLAN FILTER HERO — START =====
     v1 drops both the render and the filters at 992. The 29-floor SVG has
     hotspots a few pixels tall, so it is genuinely unusable at this width and
     is hidden the same way. The filters are KEPT (v1 hides them too) — a
     floorplan page you cannot filter on a tablet is a functional loss, and
     they cost nothing once stacked. Folded into this theme existing 1024
     block rather than adding v1 992 breakpoint. */
  .special-floorplan-filters {
    padding: 100px 15px 0;
  }

  .special-floorplan-filters .flp-intro {
    position: relative;
    top: auto;
    left: auto;
    width: 100%;
  }

  .special-floorplan-filters .flp-image-container {
    width: 100%;
  }

  .special-floorplan-filters .special-floor-picker {
    display: none;
  }

  /* no render left to overlap, so the -220px lift from the 1890 block is
     cancelled and the filters become a normal full-width row */
  .special-floorplan-filters .flp-filter-container {
    top: 0;
    width: 100%;
    padding: 0 0 30px;
  }
  /* ===== FLOORPLAN FILTER HERO — END ===== */
}

/* ============================================================
   768px, NOT 767px — deliberate.

   component-common.css switches the gallery component to its mobile form at
   `max-width: 768px` (dropdown replaces the buttons, .tab-content.active flips
   from flex to block so slick can take over). Every other responsive block in
   this file is 767. Putting the gallery's mobile rules in the 767 block would
   leave a one-pixel dead zone at exactly 768px, where the framework has gone
   mobile but our overrides have not. This block exists to line up with the
   framework; do not merge it into the 767 block below.
   ============================================================ */
@media (max-width: 768px) {
  /* ===== GALLERY PAGE — START =====
     One card per view: the framework turns the active pane into a slick
     carousel at this width, so the cards must be full width. */
  .gallery-section.new-section .gallery-card,
  .gallery-section.new-section .single-virtual-tour {
    flex: 0 0 100%;
    max-width: 100%;
  }

  /* the framework flips .tab-content.active to display:block here for slick,
     so the tour grid needs its own stacking */
  .gallery-section.new-section .vr-tour-container {
    display: block;
  }

  .gallery-section.new-section .single-virtual-tour {
    margin-bottom: 16px;
  }
  /* ===== GALLERY PAGE — END ===== */
}

@media (max-width: 767px) {

  /* ===== POLICY PAGES — START =====
     v1 unfloats the pet photo at this breakpoint (live style.css:3230-3238):
     at 45% it leaves a two-word ragged column beside it on a phone. The copy
     that followed it has to clear as well. Applies to all four policy pages
     because the markup is editor content and can appear on any of them. */
  .policy-section img.pet-policy-img {
    float: none;
    width: 100%;
    max-width: 100%;
    margin: 0 0 15px;
  }

  .policy-section .img-cont {
    clear: both;
    padding-top: 10px;
  }

  .policy-section .policy-text h3,
  .policy-section .policy-text h4 {
    margin-top: 24px;
  }
  /* ===== POLICY PAGES — END ===== */

  /* ===== AMENITIES TABS — START =====
     Stack the photo over the copy. Without this the heading clipped mid-word
     (COMMUN / AMENITI) in a 38%-wide column on a 425px screen. */
  .amenities-page-gallery .amenities-container .left-col,
  .amenities-page-gallery .amenities-container .right-col {
    width: 100%;
    padding-left: 0;
  }

  .amenities-page-gallery .amenities-container .right-col {
    margin-top: 24px;
  }

  /* the framework already drops the feature list to one column here
     (component-common.css:3994); this matches it for the
     .amenities-page-gallery rule that would otherwise keep two */
  .amenities-page-gallery ul.amenities-grid {
    column-count: 1;
  }

  /* ===== AMENITIES TABS — END ===== */

  /* ===== AMENITIES MASONRY GALLERY — START =====
     The masonry had no responsive step: 25% / 33% / 50% columns with pixel
     heights and a `margin-left: calc(50% + 15px)` indent on #1 held all the
     way down, so on a phone the tiles became slivers with a 15px gutter
     eating most of the column and the 320/350px fixed heights stretched them
     into towers. Below 767 the artistic offsets are dropped and every tile
     becomes a uniform two-up.

     The `:nth-child(n)` on the reset is deliberate — the base rules are
     (0,5,2) via their own :nth-child(), so a plain selector cannot outrank
     them; this matches their specificity and wins on order. */
  .amenities-page-gallery .amenities-gallery {
    margin: 40px 0;
  }

  .amenities-page-gallery svg.amnety-svg {
    width: 260px;
    max-width: 50%;
    margin-top: 20px;
  }

  .amenities-page-gallery ul.modular-gallery-ul {
    margin-top: 60px;
    padding: 0;
  }

  .amenities-page-gallery ul.modular-gallery-ul li.modular-image-container,
  .amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(n) {
    float: none;
    width: calc(50% - 16px);
    height: 200px;
    min-height: 0;
    margin: 0 8px 16px;
  }

  /* #1 keeps its half-width indent so the LVL29 watermark still has the left
     half of the first row to itself, as it does on desktop */
  .amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(1) {
    margin-left: calc(50% + 8px);
  }
  /* ===== AMENITIES MASONRY GALLERY — END ===== */

  /* ===== APPLY NOW BUTTON — START =====
     v1 hides the floating circle on phones (live style.css:3223-3226) because
     it lands on top of the content; the mobile menu's own Apply Now button is
     what carries the action from here down. */
  a.apply-link {
    display: none;
  }
  /* ===== APPLY NOW BUTTON — END ===== */

  /* ===== LIGHT INNER PAGES — START =====
     v1 drops the FAQ banner to 320px here (live style.css:3240) and tightens
     the card to 20px 18px (:3243). Applied to all three light pages so they
     stay a family. */
  .page-fq .inner-hero-section,
  .page-rs .inner-hero-section,
  .page-rd .inner-hero-section,
  .page-bl .inner-hero-section,
  .page-bs .inner-hero-section {
    height: 320px;
  }

  .page-fq .inner-hero-section .inner-hero-title,
  .page-rs .inner-hero-section .inner-hero-title,
  .page-rd .inner-hero-section .inner-hero-title {
    font-size: 3.2rem;
  }

  .page-fq .new-section.faq-section .faq-item,
  .page-rs .single-resource-item,
  .page-rd .single-resident-section {
    border-width: 1px;
  }

  .page-rs .single-resource-item,
  .page-rd .single-resident-section {
    padding: 20px 18px;
  }
  /* ===== LIGHT INNER PAGES — END ===== */

  /* ===== RESOURCES PAGE — START ===== */
  .page-rs .single-resource-item {
    flex: 0 0 100%;
    max-width: 100%;
  }
  /* ===== RESOURCES PAGE — END ===== */

  /* ===== TOUR PAGE — START ===== */
  .page-tr .single-virtual-tour {
    flex: 0 0 100%;
    max-width: 100%;
  }
  /* ===== TOUR PAGE — END ===== */
  /* The .desktop-bg / .mob-bg swap is the framework's job here
     (component-common.css:3739 and :3746); the 56vw backdrop needs no override. */

  /* ===== CONTACT PAGE — START =====
     No form rules needed: component-common.css:3401-3470 already stacks the
     columns, resizes the fields and shrinks the custom controls at 768. Only
     the contact panel, which the framework never stacks, is handled here. */
  .page-ct .contact-map .container.d-flex {
    flex-flow: column;
    gap: 30px;
  }

  .page-ct .contact-map .contact-info,
  .page-ct .contact-map .map-area {
    width: 100% !important;
  }

  .page-ct #footer-google-map {
    height: 60vw;
    min-height: 300px;
  }
  /* ===== CONTACT PAGE — END ===== */

  /* ===== NEIGHBORHOOD HERO + INTRO — START =====
     No room for a side column on a phone: the copy goes full width, and the
     rotated CTA is dropped (v1 hides it at this breakpoint too). */
  .page-nb .intro-type-1.intro-to-right .content-wrapper {
    max-width: 100%;
    padding: 150px 20px 40px;
  }

  .page-nb .location-content__cta {
    display: none;
  }
  /* ===== NEIGHBORHOOD HERO + INTRO — END ===== */

  /* ===== NEIGHBORHOOD MAP + PLACES — START =====
     One card per view on a phone. It used to be 80%, which left a sliced
     neighbour card at the edge; at 100% — with the scroll snapping and the
     arrows stepping a whole card — the strip shows exactly one place at a
     time and never a half one.

     The strip's own prev/next chevrons STAY on mobile (they used to be hidden
     with the filter rail's): they are the only way to page a one-card strip
     other than an undiscoverable swipe. Only .nbp-nav-btn — the filter rail's
     arrows — is hidden, because component-common.css:4053 hides that rail
     itself and swaps in the <select>. */
  .neighborhood.new-section .nbp-places-list .nb-places-ul li {
    width: 100%;
    padding: 0 10px;
    border-right: 0;
  }

  .neighborhood.new-section .nbp-nav-btn {
    display: none;
  }

  /* the arrows flank the card, so the strip is what is left between them */
  .neighborhood.new-section .nbp-places-scroller {
    width: 100%;
  }

  .neighborhood.new-section .nbp-places-nav {
    width: 26px;
    height: 26px;
    font-size: 1rem;
  }

  .neighborhood.new-section .nbp-places-list {
    padding: 0 5px 15px;
  }

  .neighborhood.new-section .map-canvas {
    height: 45vh;
    min-height: 320px;
  }
  /* ===== NEIGHBORHOOD MAP + PLACES — END ===== */

  /* --- Header: below the squeeze range, CSS hides the same three blocks the
     JS would have hidden. main.js strips .hidden here, so these must be
     unconditional. The burger stays visible at every width. --- */
  ._header .header-menu,
  ._header .header-contact,
  ._header .header-cta {
    display: none;
  }

  ._header {
    padding: 12px 0;
  }

  ._header .logo-wrapper a.logo img {
    height: 40px;
  }

  /* --- Footer: policy links stack, separators off (footer-3's 767) --- */
  .footer ul.policy-nav {
    flex-direction: column;
    justify-content: center;
  }

  .footer ul.policy-nav li a::after {
    display: none;
  }

  .footer.new-section ul.policy-nav li a {
    text-decoration: underline;
  }

  .footer .footer-menu {
    gap: 1rem;
  }

  .footer .footer-submenu {
    text-align: left;
  }

  .footer .footer-menu.submenu-wrap .footer-menu-item {
    text-align: left;
  }

  .footer .footer-address-wraper {
    gap: 20px;
  }

  .footer .footer-top-wraper {
    padding: 25px 12px;
  }

  .footer .footer-lower {
    padding: 16px 12px;
  }

  .footer .footer-policy-nav,
  .footer .footer-property-icons {
    padding-left: 0;
    padding-right: 0;
  }

  .footer .cb-logo-wrap {
    padding-left: 0;
  }

  /* --- Floorplan rows: columns stack, dividers off --- */
  .floorplan-page .flp-card {
    flex-flow: column;
    align-items: stretch;
    text-align: center;
  }

  .floorplan-page .flp-card-body,
  .floorplan-page .flp-card-header,
  .floorplan-page .flp-card-footer {
    width: 100%;
    border: none;
  }

  .floorplan-page .flp-card-body {
    height: 200px;
    margin-bottom: 20px;
  }

  .floorplan-page .flp-card-header .flp-title-wrap,
  .floorplan-page .flp-card-header .flp-details,
  .floorplan-page .flp-card-footer .flp-card-meta,
  .floorplan-page .flp-btn-wrap {
    width: 100%;
    padding: 12px 0;
    border: none;
  }

  .floorplan-page .flp-card-footer .flp-text-wrap {
    justify-content: center;
  }

  /* --- Home map: shorter map, address blocks stack full width --- */
  .home-map .map-wrapper,
  .home-map .map-wrapper iframe {
    min-height: 400px;
    height: 400px;
  }

  .home-map .map-contact .address,
  .home-map .map-contact .contact {
    width: 100%;
    margin-bottom: 25px;
    padding: 0;
    border: none;
  }

  /* --- Footer CTA: tighter padding, like v1. Parallax is dropped here —
     a fixed background is janky on touch devices, which is why v1 also
     switches to background-attachment:scroll at this breakpoint. --- */
  .footer-cta {
    padding: 165px 0 75px;
    clip-path: none;
  }

  .footer-cta .right-col {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    height: auto;
  }

  .footer-cta .footer-cta-wrapper {
    padding-left: 40px;
    padding-right: 40px;
  }

  .footer-cta .cta-buttons {
    margin-top: 25px;
  }

  .footer-cta .cta-buttons > a {
    margin: 40px 0;
  }

  .footer-cta .footer-cta-content .cta-text {
    font-size: 1.143rem;
    line-height: 1.5;
  }

  /* --- Additional content 3: stacks here (not at 992), like v1 --- */
  .additional-content-3 .container {
    display: block;
    padding: 75px 20px 30px;
    border-bottom-left-radius: 100px;
    text-align: center;
  }

  .additional-content-3 .section-details,
  .additional-content-3 .section-counters {
    width: 100%;
  }

  .additional-content-3 .container h2 {
    font-size: 1.714rem;
  }

  .additional-content-3 .section-details .section-content p {
    font-size: 1.143rem;
  }

  .additional-content-3 .single-counter-item {
    padding: 10px;
  }

  .additional-content-3 .single-counter-item span.counter-number {
    font-size: 1.571rem;
  }

  .additional-content-3 .single-counter-item span.counter-detail {
    font-size: 1rem;
  }

  /* --- Home gallery: shorter images and a smaller arrow block, like v1 --- */
  .home-gallery {
    padding-top: 55px;
    padding-bottom: 55px;
  }

  .home-gallery .gallery-content {
    margin-bottom: 30px;
  }

  .home-gallery .magnific-img img {
    height: 260px;
  }

  .home-gallery .gallery-arrows {
    margin: -54px auto 0;
  }

  .home-gallery .gallery-arrows .slick-prev-arrow,
  .home-gallery .gallery-arrows .slick-next-arrow {
    width: 64px;
    height: 54px;
  }


  /* --- Hero --- */
  .hero-slider,
  .hero-slider .slick-slide {
    height: 100vh;
    min-height: 480px;
  }

  .slide-bg.desktop-bg {
    display: none;
  }

  .slide-bg.mob-bg {
    display: block;
  }

  /* Needs the full selector to outrank the base
     .hero-banner.video-banner .slide-bg.mob-bg { display: none } above. */
  .hero-banner.video-banner .slide-bg.mob-bg {
    display: block;
  }

  /* Video hero: drop the embed and the poster, show the still instead —
     background video is wasted bandwidth and unreliable autoplay on phones. */
  .hero-banner.video-banner .video-iframe-wrapp,
  .hero-banner.video-banner .vimeo-thumbnail,
  .hero-banner.video-banner .wistia_responsive_padding {
    display: none;
  }

  .hero-banner.video-banner .video-wrapper {
    height: 100vh;
    min-height: 480px;
  }

  .hero-banner.video-banner .video-container {
    bottom: 100px;
  }

  .slide-flex-wrapper {
    padding-bottom: 100px;
  }

  .hero-banner .section-buttons {
    gap: 12px;
    margin-top: 18px;
  }

  .hero-slider .slick-dots {
    bottom: 58px;
  }

  /* component-common.css hides .bottom-section-link entirely at this
     breakpoint, so no sizing is needed here. */
  .bottom-section-link-wrapper {
    bottom: 16px;
  }

  /* --- Floorplan listing: below the tablet range the five-column row has no
     width left, so the card stacks. These must be restated at .new-section
     specificity for the same reason the base rules are. --- */
  .new-section.floorplan-page .flp-card {   
    flex-flow: column;
    align-items: stretch;
  }

  .new-section.floorplan-page .flp-card-body,
  .new-section.floorplan-page .flp-card-header,
  .new-section.floorplan-page .flp-card-footer {
    flex: 0 0 auto;
    width: 100%;
    max-width: 100%;
  }

  /* dividers turn from vertical rules into horizontal ones */
  .new-section.floorplan-page .flp-card-body {
    height: 180px;
    border-right: 0;
    border-bottom: 2px solid rgba(0, 0, 0, 0.1);
  }

  .new-section.floorplan-page .flp-card-header {
    flex-flow: column;
  }

  .new-section.floorplan-page .flp-card-header .flp-title-wrap {
    flex-flow: column;
  }

  .new-section.floorplan-page .flp-card-header .flp-title-wrap > .flp-more-details,
  .new-section.floorplan-page .flp-card-header .flp-details,
  .new-section.floorplan-page .flp-card-footer .flp-card-meta {
    width: 100%;
    padding: 15px 0;
    border-left: 0;
    border-right: 0;
    border-bottom: 2px solid rgba(0, 0, 0, 0.1);
  }

  .new-section.floorplan-page .flp-card-footer {
    flex-flow: column;
  }

  .new-section.floorplan-page .flp-btn-wrap {
    justify-content: flex-start;
    width: 100%;
    padding: 15px 0 0;
  }

  /* back into the flow — there is no image column to float over any more */
  .new-section.floorplan-page .flp-icon-wrap {
    position: static;
    padding-top: 10px;
  }

  /* ===== FLOORPLAN FILTER HERO — START =====
     One filter per row on a phone: two 50% columns leave the longer labels
     ("ALL BEDROOMS", "HOUSING TYPE") colliding with the arrow. */
  .special-floorplan-filters {
    padding: 90px 15px 0;
  }

  .special-floorplan-filters .flp-filter-container .filter-box {
    width: 100%;
    margin: 10px 0;
  }
  /* ===== FLOORPLAN FILTER HERO — END ===== */

  /* ===== Five-row scroll cap — START =====
     Stacked rows are roughly three times taller here, so a 900px cap would
     cut the first row in half. Released: the page scrolls normally instead. */
  .new-section.floorplan-page .flp-row {
    max-height: none;
    overflow-y: visible;
  }
  /* ===== Five-row scroll cap — END ===== */

  /* ===== FAQ PAGE — START =====
     component-common.css:3999-4033 already cuts the question, answer and
     search-bar padding here (with !important) and swaps the button row for
     the <select>. Only the 50px chevron is left oversized against that
     tighter padding. */
  .page-fq .new-section.faq-section .faq-question {
    gap: 12px;
  }

  .page-fq .new-section.faq-section .faq-question .chevron-type-1 {
    width: 40px;
    height: 40px;
  }
  /* ===== FAQ PAGE — END ===== */
}

@media (max-width: 575px) {

  /* ===== POLICY PAGES — START =====
     v1 shrinks the pet CTA buttons at 468 (live style.css:3319) so three of
     them still fit a phone row; folded into this theme's nearest existing
     breakpoint rather than adding a new one. Full width beats three cramped
     pills — each is a separate action. */
  .policy-section .pet-cta {
    flex-flow: column;
  }

  .policy-section a.pet-btn {
    width: 100%;
    padding: 0.9em 1em;
    text-align: center;
  }

  .policy-section .policy-text blockquote {
    margin: 20px 0;
    padding-left: 16px;
  }
  /* ===== POLICY PAGES — END ===== */

  /* --- Footer menu: flat list drops from column-flow to a single column,
     and the submenu divider tightens. footer-3 does this at 480; folded into
     this theme's nearest existing breakpoint rather than adding a new one. --- */
  .footer .footer-menu.no-submenu-wrap {
    grid-auto-flow: row;
  }

  .footer .footer-menu.submenu-wrap {
    padding-right: 12px;
  }

  .footer .footer-menu-wraper {
    gap: 12px;
  }

  /* --- Hero --- */
  .slide-flex-wrapper {
    padding-bottom: 92px;
  }

  .hero-banner.video-banner .video-container {
    bottom: 92px;
  }

  .hero-banner .section-buttons {
    flex-flow: column;
    align-items: center;
  }

  .hero-banner .btn {
    width: 100%;
    max-width: 280px;
  }

  /* ===== AMENITIES MASONRY GALLERY — START =====
     Still two-up at phone widths — 17 tiles in one column is a very long
     scroll — just shorter, so a ~170px-wide tile is not taller than it is
     wide. --- */
  .amenities-page-gallery ul.modular-gallery-ul li.modular-image-container,
  .amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(n) {
    height: 150px;
    margin: 0 6px 12px;
    width: calc(50% - 12px);
  }

  .amenities-page-gallery .amenities-gallery ul.modular-gallery-ul li.modular-image-container:nth-child(1) {
    margin-left: calc(50% + 6px);
  }

  .amenities-page-gallery ul.modular-gallery-ul {
    margin-top: 40px;
  }
  /* ===== AMENITIES MASONRY GALLERY — END ===== */
}

/* ============================================================
   SECTION: RESPONSIVE — END
   ============================================================ */
