/* =============================================
   Delta Realty, LLC — Global Styles
   ============================================= */

/* ---------- Reset & Base ---------- */
*,
*::before,
*::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

:root {
    --black: #1A1A1A;
    --gold: #FFD700; /* Bright sunshine yellow */
    --gold-dark: #b0912f;
    --gold-text: #856800; /* accessible gold for TEXT on light backgrounds (~5.3:1, WCAG AA 1.4.3). --gold and --gold-dark both fail AA as text on white — use them only for fills or text on dark. */
    --red: #DC2626; /* Karen's brand red — used in her Facebook content and print materials. Reserved for high-impact accents (status badges, alert CTAs) and pairs with var(--gold) on the page-header descriptor for an on-brand red+yellow flag. */
    --white: #FFFFFF;
    --gray-bg: #F5F5F5;
    --gray-text: #333333;
    --gray-light: #E5E5E5;
    --gray-muted: #717171; /* darkened from #888888 (~3.5:1, failed WCAG AA 1.4.3 on small text) to ~4.9:1 on white. Used for form labels, hints, table headers, results counts. */
    --font-heading: 'Playfair Display', Georgia, serif;
    --font-body: 'Inter', 'Helvetica Neue', sans-serif;
    --transition: 0.35s ease;
    --radius: 6px;
    --shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
    --shadow-lg: 0 12px 36px rgba(0, 0, 0, 0.12);
}

html {
    scroll-behavior: smooth;
    overflow-x: hidden;
    max-width: 100vw;
}

body {
    font-family: var(--font-body);
    color: var(--gray-text);
    background: var(--white);
    line-height: 1.7;
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
    max-width: 100vw;
}

img {
    display: block;
    max-width: 100%;
}

a {
    text-decoration: none;
    color: inherit;
}

ul {
    list-style: none;
}

address {
    font-style: normal;
}

/* Form-input base: 16px is the threshold below which iOS Safari
   auto-zooms into the focused field (and never auto-zooms back out),
   leaving the user stuck zoomed in with the sticky mobile CTA bar
   cut off. Setting all input/select/textarea elements to 16px+
   universally is Apple's documented recommended fix — the alternative
   (`maximum-scale=1` / `user-scalable=no` on the viewport meta) would
   disable pinch-zoom site-wide, which breaks accessibility for
   low-vision users. Class-level overrides below (.filter-input,
   .form-input, etc.) are also held at 16px so they don't undercut
   this. */
input,
select,
textarea {
    font-size: 16px;
}

.container {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 24px;
}

/* ---------- Performance: Extracted Inline Styles ---------- */
/* These classes replace inline style="" attributes so the browser can
   cache them in the stylesheet instead of re-parsing them on every page
   load. Moving styles from HTML to CSS also reduces HTML file size and
   keeps all styling in one maintainable location. */

/* PLACEHOLDER — swap for a real local Delta Realty listing photo before launch.
   Current Unsplash image is a free-to-use charming rural/small-town home with front porch.
   Target vibe: warm, inviting, unmistakably residential SE Missouri — not urban, not luxury. */
.hero-bg-default {
    background-image: url('https://images.unsplash.com/photo-1570129477492-45c003edd2be?w=1600&auto=format&fit=crop');
}

.cta-bg-default {
    background-image: url('https://images.unsplash.com/photo-1500382017468-9049fed747ef?w=1600');
}

.gold-line-left {
    margin-left: 0;
}

.bg-gray {
    background: var(--gray-bg);
}

.form-submit-left {
    text-align: left;
}

/* ---------- Shared Elements ---------- */
.gold-line {
    width: 60px;
    height: 2px;
    background: var(--gold);
    margin: 16px auto 0;
}

.section {
    padding: 96px 0;
}

/* Tightened gap between the listings grid and the Recently Sold
   social-proof section. Both sections inherit `.section { padding:
   96px 0 }`, which stacks to 192px between the last listing card and
   the Recently Sold heading — large enough that scrolling visitors
   were missing the section entirely. Pulling the inner padding to
   32px on each side lands the gap at 64px on desktop (well inside
   the site's typical inter-section rhythm) without making the two
   sections butt together visually. The mobile variant below scales
   the gap to ~44px to match smaller-viewport spacing density. Other
   sections that use `.section` are untouched. */
.listings-results {
    padding-bottom: 32px;
}
.recently-sold-section {
    padding-top: 32px;
}

.section-header {
    text-align: center;
    margin-bottom: 56px;
}

.section-header h2 {
    font-family: var(--font-heading);
    font-size: clamp(1.8rem, 3.5vw, 2.4rem);
    font-weight: 600;
    color: var(--black);
}

/* Optional one-line framer beneath the .gold-line accent. Used on
   social-proof / context sections (e.g., Recently Sold) where a brief
   sentence helps a scanning visitor understand what the section is
   without reading the cards. */
.section-subtitle {
    margin-top: 16px;
    font-family: var(--font-body);
    font-size: 1rem;
    color: var(--gray-text);
    max-width: 640px;
    margin-left: auto;
    margin-right: auto;
}

/* ---------- Buttons ---------- */
.btn {
    display: inline-block;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 0.9rem;
    padding: 14px 32px;
    border-radius: var(--radius);
    border: 2px solid transparent;
    cursor: pointer;
    transition: all var(--transition);
    text-align: center;
}

.btn-gold {
    background: var(--gold);
    color: var(--black);
    border-color: var(--gold);
}

.btn-gold:hover {
    background: #E6C200;
    border-color: #E6C200;
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(255, 215, 0, 0.3);
    transition: all 0.2s ease;
}

.btn-gold:active {
    transform: translateY(0);
    box-shadow: 0 2px 4px rgba(255, 215, 0, 0.2);
}

.btn-gold:disabled {
    background-color: #999;
    border-color: #999;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

.btn-outline-gold {
    background: transparent;
    color: var(--white);
    border-color: var(--gold);
}

.btn-outline-gold:hover {
    background: var(--gold);
    color: var(--black);
    transform: translateY(-2px);
}

.btn-lg {
    padding: 16px 40px;
    font-size: 1rem;
}

.btn-sm {
    padding: 8px 16px;
    font-size: 0.85rem;
}

/* ---------- Navigation ---------- */
.trust-bar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1001;
    background: #1A1A1A;
    color: #FFFFFF;
    font-family: var(--font-body);
    font-size: 13px;
    text-align: center;
    padding: 8px 0;
}

.navbar {
    position: fixed;
    top: 32px;
    left: 0;
    right: 0;
    z-index: 1000;
    background: var(--black);
    transition: box-shadow var(--transition);
}

.navbar.scrolled {
    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.3);
}

.nav-container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 76px;
}

/* Home-page navbar variant: no brand, nav links centered full-width */
.navbar-home .nav-container {
    justify-content: center;
}

.navbar-home .nav-right {
    flex: 1;
    justify-content: center;
}

.navbar-home .nav-links {
    gap: 48px;
}

.logo {
    font-family: var(--font-heading);
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--white);
}

.logo span {
    font-weight: 400;
    color: var(--gold);
}

/* Logo sized to match nav height — use height only, width: auto preserves aspect ratio */
.nav-logo {
    height: 30px;
    width: auto;
    display: block;
}

/* Nav brand — logo + text side by side */
.nav-brand {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    text-decoration: none;
}

/* Brand text scales alongside the nav links (1.4 → 1.85rem, same ~1.32×
   factor) so the brand stays comfortably above the link size in the
   visual hierarchy. */
.nav-brand-text {
    font-family: var(--font-heading);
    font-size: 1.85rem;
    color: var(--white);
    letter-spacing: 0.5px;
    line-height: 1.2;
}

.nav-brand-accent {
    color: var(--gold);
}

.nav-right {
    display: flex;
    align-items: center;
    gap: 40px;
}

.nav-links {
    display: flex;
    align-items: center;
    gap: 32px;
}

/* Nav link typography sized for senior-user readability (Karen's primary
   audience). 1.125rem = 18px — the WCAG-comfortable floor for older eyes
   on a non-zoomed desktop browser. Weight 600 (semibold) thickens the
   letterforms enough to read clearly against the dark navbar without
   crossing into "headline-heavy" territory. The same sizing flows into
   the mobile drawer (no breakpoint override) so phone users benefit too. */
.nav-links a {
    font-size: 1.125rem;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.75);
    transition: color var(--transition);
}

.nav-links a:hover,
.nav-links a.nav-active {
    color: var(--gold);
}

/* CTA button inside nav-links keeps dark text and matches sibling nav-link typography.
   Without this override, .nav-links a wins specificity and forces font-weight: 600 + light color. */
.nav-links a.btn-gold,
.nav-links a.btn-gold:hover,
.nav-links a.btn-gold:focus {
    color: var(--black);
    font-family: var(--font-body);
    font-weight: 600;
}

/* Schedule Consultation CTA — text scales with nav links so the two stay
   visually balanced. Padding nudges up slightly (10→12 vert, 24→26 horiz)
   so the button still hugs its label without looking bloated at the new size. */
.nav-cta {
    padding: 12px 26px;
    font-size: 1.125rem;
}

.mobile-toggle {
    display: none;
    flex-direction: column;
    gap: 5px;
    background: none;
    border: none;
    cursor: pointer;
    padding: 4px;
}

.mobile-toggle span {
    display: block;
    width: 24px;
    height: 2px;
    background: var(--white);
    border-radius: 1px;
    transition: all var(--transition);
}

.mobile-toggle.active span:nth-child(1) {
    transform: rotate(45deg) translate(5px, 5px);
}

.mobile-toggle.active span:nth-child(2) {
    opacity: 0;
}

.mobile-toggle.active span:nth-child(3) {
    transform: rotate(-45deg) translate(5px, -5px);
}

/* ---------- Hero ---------- */
.hero {
    position: relative;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    /* WCAG conformant fallback: a solid dark base UNDER the background image.
       If the hero image fails to load, the gold/white text still sits on dark
       (gold on near-black after the overlay is ~13:1 — AAA for large text)
       instead of dropping onto the white page background (~2.8:1, fails).
       Hidden behind the image in the normal case, so no visual change. */
    background-color: var(--black);
}

.hero-overlay {
    position: absolute;
    inset: 0;
    /* Pure-black gradient darkens the image just enough for white text to stay readable
       over lighter regions of the photo (e.g. sky, porch highlights) without losing detail. */
    background: linear-gradient(180deg, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.8) 100%);
}

.hero-content {
    position: relative;
    text-align: center;
    max-width: 800px;
    padding: 24px;
}

/* Home-page hero brand — typographic statement centered above the h1.
   Sized larger than the h1 (which uses clamp(2rem, 5vw, 3.4rem)) so it
   reads as the top of the visual hierarchy. Dual text-shadow gives
   soft contrast over the hero image without a visible box. */
.hero-brand {
    font-family: var(--font-heading);
    font-size: clamp(2.75rem, 7vw, 4.75rem);
    font-weight: 700;
    color: var(--gold);
    letter-spacing: 0.5px;
    line-height: 1.15;
    margin-bottom: 24px;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8), 0 2px 12px rgba(0, 0, 0, 0.6);
}

.hero-brand-accent {
    color: var(--gold);
}

/* Rental link in footer — noticeable but not competing with main CTAs. */
.footer-rental-link {
    margin-top: 16px;
    font-size: 0.8rem;
    color: rgba(255, 255, 255, 0.7);
}

.footer-rental-link a {
    color: var(--gold);
    text-decoration: none;
    transition: color 0.3s ease;
}

.footer-rental-link a:hover {
    color: #CCCCCC;
}

.hero-content h1 {
    font-family: var(--font-heading);
    font-size: clamp(2rem, 5vw, 3.15rem);
    font-weight: 700;
    color: var(--white);
    line-height: 1.25;
    margin-bottom: 20px;
}

/* Homepage hero descriptor stays white. The hero already carries heavy
   yellow saturation (brand wordmark, both CTAs, scroll indicator, top
   banner), so layering red onto the descriptor reads as visual cacophony
   rather than brand. White is the calming neutral here. The class is
   only used on index.html so this rule is effectively homepage-scoped
   without needing a body-class hook. The brand-red rollout still applies
   on the inner-page descriptors (.page-header p) below. */
.hero-subtitle {
    font-size: clamp(0.95rem, 1.8vw, 1.15rem);
    color: rgba(255, 255, 255, 0.95);
    font-weight: 300;
    margin-bottom: 40px;
    line-height: 1.7;
}

.hero-buttons {
    display: flex;
    gap: 16px;
    justify-content: center;
    flex-wrap: wrap;
}

/* ---------- Stats Bar ---------- */
.stats-bar {
    background: var(--black);
    padding: 52px 0;
}

.stats-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 24px;
    text-align: center;
}

.stat-number {
    font-family: var(--font-heading);
    font-size: 2.4rem;
    font-weight: 700;
    color: var(--gold);
    line-height: 1.2;
}

.stat-suffix {
    font-family: var(--font-heading);
    font-size: 2.4rem;
    font-weight: 700;
    color: var(--gold);
}

.stat-label {
    display: block;
    font-size: 0.85rem;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.7);
    margin-top: 6px;
}

/* ---------- Featured Listings ---------- */
.listings-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 32px;
}

.property-card {
    background: transparent;
    border: 1px solid var(--black);
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow);
    transition: transform var(--transition), box-shadow var(--transition);
    /* GPU compositing hint that doesn't occupy the transform property —
       leaves transform free for the hover translateY() so hover-in and
       hover-out animate smoothly without matrix decomposition snaps. */
    will-change: transform;
}

.property-card:hover {
    transform: translateY(-6px);
    box-shadow: var(--shadow-lg);
}

.property-image {
    position: relative;
    height: 220px;
    overflow: hidden;
}

.property-image img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.5s ease;
    will-change: transform;
}

.property-card:hover .property-image img {
    transform: scale(1.04);
}

.property-badge {
    position: absolute;
    top: 14px;
    left: 14px;
    background: var(--gold);
    color: var(--black);
    font-size: 0.7rem;
    font-weight: 700;
    padding: 5px 14px;
    border-radius: 20px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* Red status badge variant — used for "Under Contract". Same shape and
   position as the gold badge; only the colorway changes. White-on-#DC2626
   gives ~4.6:1 contrast which clears WCAG AA for normal-sized text. */
.property-badge.is-red {
    background: var(--red);
    color: var(--white);
}

/* Secondary badge slot — the home Featured grid can show TWO badges on one
   card (status top-left + ↓$ price-reduction top-right). The status badge
   keeps the base .property-badge top-left position; this modifier flips a
   SECOND .property-badge to the top-right corner so the two don't overlap.
   Colorway is inherited from .property-badge (gold) — the reduction pill is
   gold like the ACTIVE status badge, matching the listings-page reduction
   pill. No new color declared here; var(--gold)/var(--red) come from the
   base rules above. */
.property-badge--secondary {
    left: auto;
    right: 14px;
}

/* ---------- Sold Listing Treatment ----------
   Trigger: JS adds .is-sold to a card whose status === "sold". Sold
   listings are filtered OUT of the main grid in this iteration (they
   move to a future Recently Sold section), but the styling lives here
   so the visual is ready the moment the first sold listing flows in. */
.property-card.is-sold {
    opacity: 0.85;
    /* Recently Sold cards are intentionally non-interactive (no anchor
       wrapper, no click handlers). Reset the default card lift on
       hover so the visual cue stays consistent with the actual
       behavior — nothing happens, so nothing animates. */
    cursor: default;
}

.property-card.is-sold:hover {
    transform: none;
    box-shadow: var(--shadow);
}

/* Scope the grayscale filter to the <img> only, NOT the .property-image
   container. The container also holds the absolutely-positioned
   .property-badge.is-red SOLD badge as a sibling of the <img>; a filter
   on the parent desaturates everything inside, turning the bright red
   badge dark gray. Targeting the <img> alone keeps the photo
   grayscale while the badge keeps its full var(--red) color. */
.property-card.is-sold .property-image img {
    filter: grayscale(100%);
}

/* The SOLD badge itself reuses .property-badge.is-red (defined above) —
   same red pillow as UNDER CONTRACT, just a different label. The earlier
   diagonal banner overlay was visually dominating the photo; between the
   small badge, the grayscale filter, and the section heading "Recently
   Sold", context is unambiguous without the large overlay. */

.property-info {
    padding: 24px;
    background: var(--white);
}

/* Card flex-column treatment — applied to BOTH the full listings grid
   (#listingsGrid on listings.html) AND the homepage Featured grid
   (#featuredListingsGrid on index.html) so the shared card markup
   produced by js/card-render.js renders identically on both pages.

   Why flex-column matters: the card uses `<a class="property-image">`
   as the photo wrapper so the entire image area is clickable. An <a>
   is inline by default — `height: 220px` on .property-image would be
   ignored, collapsing the photo. Making the parent .property-card a
   flex container "blockifies" the anchor as a flex item, so its
   declared height applies. Without this rule the homepage cards
   render as just a misshapen photo + badge with the body content
   stacking incorrectly underneath.

   Side benefit (matters most on the listings page where mixed property
   types share a row): grid's default align-items: stretch equalizes
   row heights to the tallest card, and flex: 1 on .property-info
   lets the white info area absorb that extra height instead of
   leaving the var(--black) card backdrop exposed as a black bar
   under shorter Lot/Land / Farm/Acreage / Commercial cards. */
#listingsGrid .property-card,
#featuredListingsGrid .property-card,
#soldListingsGrid .property-card {
    background: var(--black);
    display: flex;
    flex-direction: column;
}

#listingsGrid .property-image,
#featuredListingsGrid .property-image,
#soldListingsGrid .property-image {
    /* flex-shrink: 0 holds the photo at its 220px height when the
       parent card is stretched taller in a mixed-height row. */
    flex-shrink: 0;
}

/* Listings-page-only 1px subpixel-gap fix. #listingsGrid uses
   grid-template-columns: repeat(3, 1fr); when the container width
   doesn't divide evenly by 3, right-column cards land on fractional
   pixel positions and the hover transform reveals a hairline between
   the top border and the image. Scoped to #listingsGrid because the
   homepage Featured grid only renders 3 cards in a row that divides
   cleanly. .property-image already has position: relative at the
   base rule — we just offset it visually by 1px without affecting
   layout flow, so the hover transform on the parent card stays
   clean (no reflow/margin interaction). Card's overflow: hidden
   clips the 1px overlap. */
#listingsGrid .property-image {
    top: -1px;
}

#listingsGrid .property-info,
#featuredListingsGrid .property-info,
#soldListingsGrid .property-info {
    /* Fill the remaining card height (everything below the 220px photo)
       so the white background covers the entire below-photo area.
       Without this, .property-info sizes to its content and the
       var(--black) card backdrop shows below it as a black bar on
       shorter cards in a mixed-height row. */
    flex: 1;
}

.property-price {
    font-family: var(--font-heading);
    font-size: 1.4rem;
    font-weight: 700;
    color: #1A1A1A;
    background: #FFD700;
    border: 2px solid #1A1A1A;
    display: inline-block;
    padding: 2px 8px;
    border-radius: 6px;
    margin-bottom: 6px;
}

.property-address {
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--black);
    margin-bottom: 12px;
    line-height: 1.4;
}

.property-details {
    display: flex;
    gap: 16px;
    padding-bottom: 16px;
    margin-bottom: 16px;
    border-bottom: 1px solid var(--gray-light);
}

.property-details span {
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--black);
}

.property-link {
    background: #FFD700;
    color: #1A1A1A;
    text-decoration: none;
    border: 2px solid #1A1A1A;
    border-radius: 6px;
    padding: 6px 16px;
    font-weight: 700;
    font-size: 14px;
    display: inline-block;
    transition: background 0.2s ease, color 0.2s ease;
}

.property-link:hover {
    background: #1A1A1A;
    color: #FFD700;
    border-color: #1A1A1A;
}

.tour-request-section {
    position: relative;
    /* WCAG fallback color under the image — the background shorthand sets no
       color on its own, so without this the form/heading would fall onto the
       parent background if the image fails. Keeps text legible over the
       ::before overlay regardless. */
    background: var(--black) url('../images/brown-ln-mansion.jpg') center/cover no-repeat;
    background-size: cover;
    background-attachment: fixed;
    /* Locked height so inline required-field errors (up to 6, which add ~180px)
       can never grow the section and drag the fixed/cover background. Sized to
       clear the tallest state — the full form with every error showing — across
       viewports down to 320px. Must match .tour-request-container and
       .tour-success so all three states render at one fixed height. */
    min-height: 1320px;
    overflow: hidden;
}

/* iOS Safari doesn't support background-attachment: fixed and renders
   the image at a zoomed-in scale. Fall back to scroll on mobile — the
   parallax effect is desktop-only anyway. */
@media (max-width: 768px) {
    .tour-request-section {
        background-attachment: scroll;
    }
}

.tour-request-section::before {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    z-index: 0;
}

.tour-request-container {
    position: relative;
    z-index: 1;
    /* Matches .tour-request-section so the form (with or without errors) and
       the success state all occupy the same locked height. */
    min-height: 1320px;
}

.tour-success {
    display: none;
    text-align: center;
    /* Matches .tour-request-section/-container so swapping the form for the
       success message doesn't collapse the section's locked height. */
    min-height: 1320px;
    opacity: 0;
    transition: opacity 0.5s ease;
    flex-direction: column;
    align-items: center;
    padding-top: 40px;
}

.matterport-tour {
    width: 100%;
    background: #f0f0f0;
    padding: 20px;
    text-align: center;
}

.matterport-placeholder {
    font-style: italic;
    color: #666;
}

.share-buttons {
    display: flex;
    gap: 8px;
    margin-top: 12px;
    border-top: 1px solid #eee;
    padding-top: 12px;
}

.share-btn {
    background: transparent;
    border: 1px solid #ddd;
    border-radius: 50%;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: #666;
    transition: all 0.3s ease;
    padding: 0;
}

.share-facebook:hover {
    color: #1877F2;
    border-color: #1877F2;
}

.share-email:hover {
    color: var(--gold);
    border-color: var(--gold);
}

.share-copy:hover {
    color: #333;
    border-color: #333;
}

/* Visual confirmation after a successful copy. js/card-render.js adds
   .share-listing-btn--copied for ~2s on the clicked copy button. Uses
   var(--gold-dark) (project's darker brand gold) so the cue reads as
   on-brand rather than a generic green/checkmark. */
.share-listing-btn--copied {
    color: var(--gold-dark);
    border-color: var(--gold-dark);
}

/* ---------- Why Choose Us ---------- */
.why-choose {
    background: var(--gray-bg);
}

.features-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 40px;
}

.feature-card {
    text-align: center;
    padding: 40px 24px;
    background: var(--white);
    border: 1px solid var(--black);
    border-radius: var(--radius);
    transition: transform var(--transition), box-shadow var(--transition);
}

.feature-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow);
}

.feature-icon {
    font-size: 2.8rem;
    margin-bottom: 20px;
    line-height: 1;
}

.feature-card h3 {
    font-family: var(--font-heading);
    font-size: 1.2rem;
    font-weight: 600;
    color: var(--black);
    margin-bottom: 12px;
}

.feature-card p {
    font-size: 0.9rem;
    color: var(--gray-text);
    line-height: 1.7;
}

/* ---------- Testimonial ---------- */
.testimonial-section-gray {
    background: var(--gray-bg);
}

.testimonial-content {
    text-align: center;
    max-width: 720px;
    margin: 0 auto;
}

.stars {
    font-size: 1.4rem;
    color: var(--gold);
    letter-spacing: 4px;
    margin-bottom: 24px;
}

.testimonial-content .quote-mark {
    display: block;
    font-family: var(--font-heading);
    font-size: 5rem;
    color: var(--gold);
    line-height: 0.4;
    margin-bottom: 20px;
}

.testimonial-content blockquote {
    font-family: var(--font-heading);
    font-size: clamp(1.05rem, 2vw, 1.3rem);
    font-weight: 400;
    font-style: italic;
    color: var(--gray-text);
    line-height: 1.9;
    margin-bottom: 28px;
}

.testimonial-author {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--black);
}

/* Carousel: all slides stacked absolutely inside a fixed-height container
   so the section never resizes when transitioning between long and short reviews. */
.testimonial-carousel {
    position: relative;
    min-height: 280px;
}

.testimonial-slide {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    opacity: 0;
    transition: opacity 1s ease;
    pointer-events: none;
    will-change: opacity;
}

.testimonial-slide.active {
    opacity: 1;
    pointer-events: auto;
}

@media (max-width: 768px) {
    .testimonial-carousel {
        min-height: 360px;
    }
}

@media (max-width: 480px) {
    .testimonial-carousel {
        min-height: 440px;
    }
}

.testimonial-dots {
    position: relative;
    z-index: 1;
    display: flex;
    justify-content: center;
    gap: 12px;
    margin-top: 28px;
}

.testimonial-dot {
    /* 24x24 tappable area (WCAG 2.5.8 Target Size). padding + background-clip
       keep the VISIBLE dot at 10px while the button itself is 24px. */
    width: 24px;
    height: 24px;
    box-sizing: border-box;
    padding: 7px;
    border-radius: 50%;
    border: none;
    background-color: var(--gray-light);
    background-clip: content-box;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    transition: background-color 0.3s ease, transform 0.3s ease;
}

.testimonial-dot.active {
    background-color: var(--gold);
    transform: scale(1.25);
}

.testimonial-dot:hover {
    background-color: var(--gold);
}

/* ---------- Financing Callout ---------- */
.financing-callout {
    background: var(--gray-bg);
}

.financing-content {
    text-align: center;
    max-width: 700px;
    margin: 0 auto;
}

.financing-content p {
    font-size: 1.05rem;
    color: var(--gray-text);
    line-height: 1.8;
    margin-bottom: 32px;
}

/* ---------- CTA Section ---------- */
.cta-section {
    position: relative;
    padding: 100px 0;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    /* WCAG conformant fallback (same rationale as .hero): solid dark base under
       the background image so the heading/text stay legible if the image fails.
       Shared by the Home, Sell, and Contact CTA sections. */
    background-color: var(--black);
}

.cta-overlay {
    position: absolute;
    inset: 0;
    background: rgba(26, 26, 26, 0.8);
}

.cta-content {
    position: relative;
    text-align: center;
    max-width: 640px;
    margin: 0 auto;
}

.cta-content h2 {
    font-family: var(--font-heading);
    font-size: clamp(1.8rem, 3.5vw, 2.6rem);
    font-weight: 700;
    color: #DC2626;
    margin-bottom: 16px;
}

.cta-content p {
    font-size: 1rem;
    color: rgba(255, 255, 255, 0.75);
    margin-bottom: 36px;
    line-height: 1.7;
}

/* ---------- Footer ---------- */
.footer {
    background: var(--black);
    padding-top: 72px;
}

.footer-grid {
    display: grid;
    grid-template-columns: 1.5fr 1fr 1fr 1fr;
    gap: 48px;
    padding-bottom: 48px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.footer-logo {
    font-family: var(--font-heading);
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--white);
    display: inline-block;
    margin-bottom: 16px;
}

.footer-logo span {
    font-weight: 400;
    color: var(--gold);
}

.footer-about {
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.75);
    line-height: 1.7;
    margin-bottom: 16px;
}

.footer-address {
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.75);
    line-height: 1.6;
}

/* Footer credential logos — recolored to brand gold via CSS mask (source PNGs are
   black-on-transparent). Absolute asset URLs so the mask resolves on the IDX
   subdomain too (cross-origin); the go-live pages.dev->live-domain sweep covers them. */
.footer-creds { display:flex; align-items:center; gap:18px; margin-top:20px; --footer-cred-size: 130px; /* <-- ONE KNOB: change this number to resize BOTH logos */ }
.footer-cred {
    display:inline-block; width:var(--footer-cred-size); height:var(--footer-cred-size);
    background-color: var(--gold);
    -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
    -webkit-mask-position:center; mask-position:center;
    -webkit-mask-size:contain; mask-size:contain;
}
.footer-cred--eho {
    -webkit-mask-image:url("https://deltarealtyllc.com/images/equal-housing-opportunity-logo.png");
    mask-image:url("https://deltarealtyllc.com/images/equal-housing-opportunity-logo.png");
}
.footer-cred--realtor {
    -webkit-mask-image:url("https://deltarealtyllc.com/images/realtor-logo.png");
    mask-image:url("https://deltarealtyllc.com/images/realtor-logo.png");
    transform: translateY(7.5px); /* <-- nudge: increase px to push the REALTOR logo DOWN, decrease to raise it */
}

.footer-col h3,
.footer-col h4 {
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--white);
    margin-bottom: 20px;
    text-transform: uppercase;
    letter-spacing: 1px;
}

.footer-col ul li {
    margin-bottom: 10px;
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.75);
    line-height: 1.5;
}

.footer-col ul li a {
    color: rgba(255, 255, 255, 0.75);
    transition: color var(--transition);
}

.footer-col ul li a:hover {
    color: var(--gold);
}

.footer-bottom {
    padding: 24px 0;
}

.footer-bottom-inner {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.footer-bottom p {
    font-size: 0.8rem;
    color: rgba(255, 255, 255, 0.7);
}

.footer-credit strong {
    color: var(--gold);
    font-weight: 600;
}

/* ---------- Screen Reader Only (Accessibility Utility) ---------- */
/* LEARNING POINT: .sr-only hides text visually but keeps it
   readable by screen readers. This is how you label things
   for accessibility without affecting your visual design.
   You'll use this pattern on EVERY site you build. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ---------- Skip Link (WCAG 2.4.1 Bypass Blocks) ---------- */
/* The first focusable element on every page. Off-screen until it receives
   keyboard focus, then pinned visibly at top-left so a keyboard/SR user can
   jump past the nav to <main id="main-content">. Black-on-white-style high
   contrast; gold focus ring matches the rest of the site. Shared across all
   pages — each page just needs the <a class="skip-link"> + main id markup. */
.skip-link {
    position: absolute;
    left: 8px;
    top: -56px;
    z-index: 2000;
    background: var(--black);
    color: var(--white);
    padding: 10px 18px;
    border-radius: 0 0 6px 6px;
    font-family: var(--font-body);
    font-weight: 600;
    text-decoration: none;
    transition: top 0.2s ease;
}
.skip-link:focus {
    top: 0;
    outline: 2px solid var(--gold);
    outline-offset: 2px;
}

/* ---------- Listings Filter Bar ---------- */
.listings-filters {
    background: var(--gray-bg);
    padding: 32px 0;
    border-bottom: 1px solid var(--gray-light);
}

.filter-bar {
    display: flex;
    gap: 16px;
    align-items: flex-end;
    flex-wrap: wrap;
}

.filter-group {
    flex: 1;
    min-width: 160px;
}

.filter-label {
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--gray-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 6px;
}

.filter-select {
    width: 100%;
    padding: 12px 16px;
    font-family: var(--font-body);
    font-size: 16px;
    color: var(--gray-text);
    background: var(--white);
    border: 1px solid var(--gray-light);
    border-radius: var(--radius);
    cursor: pointer;
    transition: border-color var(--transition);
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23888' d='M1.41 0L6 4.58 10.59 0 12 1.41l-6 6-6-6z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    padding-right: 36px;
}

.filter-select:focus {
    outline: none;
    border-color: var(--gold);
    box-shadow: 0 0 0 3px rgba(255, 215, 0, 0.15);
}

/* City search input — mirrors .filter-select padding/sizing/focus so the
   filter bar reads as a single horizontal control set. Drops the custom
   chevron background since native datalist inputs don't render one. */
.filter-input {
    width: 100%;
    padding: 12px 16px;
    font-family: var(--font-body);
    font-size: 16px;
    color: var(--gray-text);
    background: var(--white);
    border: 1px solid var(--gray-light);
    border-radius: var(--radius);
    transition: border-color var(--transition);
}

.filter-input::placeholder {
    color: var(--gray-muted);
}

.filter-input:focus {
    outline: none;
    border-color: var(--gold);
    box-shadow: 0 0 0 3px rgba(255, 215, 0, 0.15);
}

/* City search now uses a custom <ul id="cityOptions"> dropdown rendered
   by listings-renderer.js — the native <datalist> approach was replaced
   because iOS Safari renders datalist suggestions as a tooltip-style
   popup that overlaps the input (no CSS hook to reposition). The
   ::-webkit-calendar-picker-indicator and `datalist { display:none }`
   rules from the previous implementation were removed along with the
   markup; the .filter-input rule above now stands on its own. */

/* Custom autocomplete dropdown for the city search. Anchored to the
   .filter-group-autocomplete wrapper (which is `position: relative`),
   it sits flush below the input on every browser. Hidden by default
   via the `hidden` attribute; listings-renderer toggles it as the
   user types and as suggestions become available. */
.filter-group-autocomplete {
    position: relative;
}

.city-suggestions {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin-top: 4px;
    max-height: 280px;
    overflow-y: auto;
    background: var(--white);
    border: 1px solid var(--gray-light);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    z-index: 50;
}

.city-suggestions[hidden] {
    display: none;
}

.city-suggestions li {
    padding: 12px 16px;
    font-size: 16px;
    color: var(--gray-text);
    cursor: pointer;
    border-bottom: 1px solid var(--gray-light);
    /* 44px+ tap height — WCAG 2.5.5 recommends a 44x44 minimum touch
       target. 12px padding + 16px font line-height (1.7 inherited from
       body) lands comfortably above that on touch devices. */
}

.city-suggestions li:last-child {
    border-bottom: none;
}

.city-suggestions li:hover,
.city-suggestions li[aria-selected="true"] {
    background: var(--gray-bg);
    color: var(--black);
}

.filter-btn {
    padding: 12px 32px;
    white-space: nowrap;
}

/* ---------- Results Toolbar ---------- */
.results-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 32px;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--gray-light);
}

.results-count {
    font-size: 0.9rem;
    color: var(--gray-muted);
}

.results-count strong {
    color: var(--black);
    font-weight: 600;
}

.sort-select {
    width: auto;
    min-width: 180px;
}

/* ---------- Property County Tag ---------- */
.property-county {
    font-size: 0.78rem;
    font-weight: 500;
    color: var(--black);
    margin-bottom: 12px;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

/* ---------- No Results State ---------- */
.no-results {
    text-align: center;
    padding: 80px 24px;
}

.no-results-text {
    font-family: var(--font-heading);
    font-size: 1.3rem;
    /* var(--gray-muted) #888 on white is ~3.5:1 — fails WCAG AA for
       normal-size text. Black on white is 21:1; the message reads as
       deliberate copy rather than disabled-state filler. Applies to
       every no-results context (filter empty state, listings load
       failure, the city-search empty-state CTA block). */
    color: var(--black);
    margin-bottom: 24px;
}

/* ---------- Property Card Show/Hide for Filters ---------- */
.property-card.card-hidden {
    display: none;
}

/* ---------- Team Intro ---------- */
.team-intro-content {
    max-width: 800px;
}

.team-intro-content h2 {
    font-family: var(--font-heading);
    font-size: clamp(1.8rem, 3.5vw, 2.4rem);
    font-weight: 600;
    color: var(--black);
    margin-bottom: 0;
}

.team-intro-content .gold-line {
    margin: 16px 0 0;
}

.team-intro-content p {
    font-size: 1rem;
    color: var(--gray-text);
    line-height: 1.8;
    margin-top: 24px;
}

/* ---------- Team Grid (mobile-first vertical cards) ----------
   Base layout is one column with stacked photo-on-top cards. Breakpoints
   only adjust column count: 768px → 2 columns, 1024px → 3 columns.
   The card itself stays the same shape at every viewport — no card-direction
   swap, so we don't need a media query for that. */
.team-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 32px;
}

.section-header-left {
    text-align: center;
    margin-bottom: 32px;
}

.section-header-left h2 {
    font-family: var(--font-heading);
    font-size: clamp(1.6rem, 3vw, 2rem);
    font-weight: 600;
    color: var(--black);
}

.team-leadership {
    margin-bottom: 16px;
}

/* 1px black border matches .property-card on the listings page — gives the
   team grid the same visual weight and rectangular silhouette. */
.agent-card {
    display: flex;
    flex-direction: column;
    background: var(--white);
    border: 1px solid var(--black);
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow);
    transition: transform var(--transition), box-shadow var(--transition);
}

.agent-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-lg);
}

.agent-card-photo-link {
    position: relative;
    display: block;
    color: inherit;
}

.agent-photo {
    aspect-ratio: 3 / 4;
    overflow: hidden;
    background: var(--gray-bg);
    /* Flex centering applies to whichever child renders. The img child
       takes width:100%/height:100% so flex centering is a no-op for
       photos; for the .agent-avatar fallback the flex container centers
       the circular badge inside the 3:4 photo box. */
    display: flex;
    align-items: center;
    justify-content: center;
}

.agent-photo img {
    display: block;
    width: 100%;
    height: 100%;
    max-width: 100%;
    object-fit: cover;
    object-position: center top;
}

/* Branded initials avatar — placeholder for missing team headshots.
   Karen's new headshots are in progress; until they arrive each photo
   slot renders this circular initials badge in brand colors. When a
   real photo lands, the .agent-avatar element gets swapped back to
   the original <img> tag and the surrounding card layout (sizes,
   badges, hover transforms) is untouched. data/team.json carries
   the canonical name + initials + photo state for each agent. */
.agent-avatar {
    width: 80%;
    aspect-ratio: 1 / 1;
    background: var(--gold);
    color: var(--black);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-body);
    font-weight: 700;
    font-size: clamp(2.5rem, 12vw, 5rem);
    line-height: 1;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    /* No box-shadow — the photo slot already sits inside a card with
       its own shadow/border. Doubled shadows on the avatar would push
       the slot visually forward of the rest of the card. */
}

/* Detail page hero (team/{slug}.html) — bigger circle, larger initials.
   .agent-hero-photo has max-width:480px and no aspect ratio, so the
   square avatar self-sizes by width and inherits its 1:1 height. */
.agent-hero-photo .agent-avatar {
    width: min(100%, 480px);
    margin: 0 auto;
    font-size: clamp(4rem, 14vw, 9rem);
}

/* Proportion fix for the detail page hero avatar on mobile + tablet.
   The base rule above (`clamp(4rem, 14vw, 9rem)`) was tuned for
   desktop where the circle caps at 480px and 144px text gives a
   ~30% ratio. At smaller viewports the same clamp lands a much
   tighter ratio because the font keeps growing with vw while the
   avatar diameter is already at its capped width — initials end
   up crowded against the edge.

   The .agent-hero-photo wrapper has no fixed pixel diameter to
   bump up (it's `width: min(100%, 480px)`, so on mobile it's
   already 100% of available column and on tablet it caps at 480px),
   so the lever is the font-size. Reducing each clamp tier gives
   the initials proper breathing room — a font reduction is
   mathematically equivalent to a diameter increase at a fixed
   text-to-diameter ratio.

   This is the second pass on this fix. The first pass (only mobile)
   wasn't enough — bio pages still felt cramped, primarily because
   tablet (768-1023px) wasn't covered and was still falling through
   to the desktop clamp. This pass tightens mobile a notch further
   AND adds the missing tablet tier. Desktop (>=1024px) and Karen's
   Meet-the-Owner card on team.html are intentionally untouched —
   both proportion correctly per Wes's confirmation. */
@media (max-width: 767.98px) {
    .agent-hero-photo .agent-avatar {
        font-size: clamp(2.5rem, 10vw, 3.5rem);
    }
}

@media (min-width: 768px) and (max-width: 1023.98px) {
    .agent-hero-photo .agent-avatar {
        font-size: clamp(3rem, 8vw, 5rem);
    }
}

/* Badge sits on top of the photo. Used for "Owner Broker" (Karen) and "Broker"
   (Tammy/Scott/Dawn). All other associates have no badge — keeps the visual
   hierarchy honest without splitting the grid into separate tiers. */
.agent-badge {
    position: absolute;
    top: 12px;
    left: 12px;
    background: var(--gold);
    color: var(--black);
    font-family: var(--font-body);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 6px 12px;
    border-radius: 999px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}

/* Owner Broker badge (Karen) intentionally inherits the standard .agent-badge
   gold-pill styling — visual harmony across leadership, brokers, and associates.
   Tier is communicated by card layout (full-width leadership card) and badge
   text ("Owner Broker"), not by color reversal. */

.agent-info {
    padding: 22px 24px 24px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex: 1;
}

.agent-name {
    font-family: var(--font-heading);
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--black);
}

.agent-title {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--gold-text);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.agent-bio-preview {
    font-size: 0.92rem;
    color: var(--gray-text);
    line-height: 1.6;
}

.agent-contact {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 4px;
}

.agent-contact-link {
    font-size: 0.88rem;
    font-weight: 500;
    color: var(--black);
    transition: color var(--transition);
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* Real email addresses can be longer than the phone format ("Email Amy" was
   tidy; "amy@bridgemakerllc.com" is not). break-all + slightly smaller font
   keeps the longest addresses inside the card on narrow screens. */
.agent-contact-link[href^="mailto:"] {
    font-size: 0.82rem;
    word-break: break-all;
}

.agent-contact-link:hover {
    color: var(--gold-dark);
}

.agent-contact-icon {
    color: var(--gold-dark);
}

/* View Profile button: 1px dark border + invert-on-hover, mirroring the
   .property-link pattern from the listings card so the two grids share a
   visual language. The border is 1px (not 2px like .property-link) per the
   review brief — slightly lighter weight on the smaller team card. */
.agent-card-cta {
    margin-top: auto;
    align-self: flex-start;
    border: 1px solid var(--black);
}

.agent-card-cta:hover {
    background: var(--black);
    color: var(--gold);
    border-color: var(--black);
}

/* ---------- Leadership Card ---------- */
/* Desktop turns the card into a horizontal layout with a fixed-width photo
   on the left and the bio preview / CTA on the right. Mobile stays vertical
   so it reads top-to-bottom on a phone like every other card. */
.agent-card-leadership {
    max-width: 920px;
    margin: 0 auto;
    box-shadow: var(--shadow-lg);
}

.agent-card-leadership .agent-photo {
    aspect-ratio: 3 / 4;
}

.agent-card-leadership .agent-info {
    padding: 28px;
    gap: 14px;
}

.agent-card-leadership .agent-name {
    font-size: 1.6rem;
}

.agent-card-leadership .agent-bio-preview {
    font-size: 1rem;
}

@media (min-width: 768px) {
    .team-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 32px;
    }

    .agent-card-leadership {
        flex-direction: row;
        align-items: stretch;
    }

    .agent-card-leadership .agent-card-photo-link {
        flex: 0 0 320px;
    }

    .agent-card-leadership .agent-photo {
        height: 100%;
        aspect-ratio: auto;
    }

    .agent-card-leadership .agent-info {
        padding: 36px;
    }
}

@media (min-width: 1024px) {
    .team-grid {
        grid-template-columns: repeat(3, 1fr);
    }

    .agent-card-leadership .agent-card-photo-link {
        flex: 0 0 360px;
    }
}

/* ---------- Agent Detail Page ---------- */
/* The trust bar (32px) + navbar (76px) are both position:fixed at the top of
   every page, occupying 108px total. Other pages clear them with
   .page-header { margin-top: 108px; }. Detail pages don't use .page-header
   (they lead with a breadcrumb), so we apply the same 108px offset here as
   the first element inside <main>. Without this the agent name and the top
   of the headshot get covered by the fixed header at scroll position 0. */
.agent-breadcrumb {
    padding: 132px 0 0;
    background: var(--white);
}

.agent-breadcrumb a {
    font-size: 0.92rem;
    color: black;
    font-weight: 500;
    transition: color var(--transition);
}

.agent-breadcrumb a:hover {
    color: var(--gold-dark);
}

.agent-hero {
    padding: 32px 0 56px;
    background: var(--white);
}

.agent-hero-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 32px;
    align-items: center;
}

.agent-hero-photo {
    max-width: 480px;
    margin: 0 auto;
}

/* Photo on the detail page does NOT crop. We use object-fit: contain so the
   agent's full headshot is visible regardless of source aspect ratio.
   max-height caps tall portraits (e.g., 412x800) so the hero never blows up.
   No box-shadow / border-radius on the IMG: object-fit: contain leaves
   transparent space inside the IMG box for off-ratio sources, and chrome on
   the IMG would draw a visible 480x600 rectangle around that empty space.
   Removing it lets the headshot sit naturally on the page background. */
.agent-hero-photo img {
    display: block;
    width: 100%;
    max-width: 480px;
    max-height: 600px;
    height: auto;
    margin: 0 auto;
    object-fit: contain;
    background: transparent;
}

.agent-hero-meta {
    text-align: center;
}

.agent-hero-meta h1 {
    font-family: var(--font-heading);
    font-size: clamp(1.8rem, 4vw, 2.6rem);
    font-weight: 600;
    color: var(--black);
    line-height: 1.2;
}

.agent-hero-title {
    color: var(--gold-text);
    font-weight: 600;
    font-size: 0.95rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-top: 8px;
}

.agent-hero-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 0;
    list-style: none;
    margin: 16px 0;
    justify-content: center;
}

.agent-hero-tags li {
    background: rgba(255, 215, 0, 0.14);
    color: var(--black);
    font-size: 0.85rem;
    font-weight: 500;
    padding: 5px 14px;
    border-radius: 999px;
}

.agent-hero-cta {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 20px;
    justify-content: center;
}

.agent-hero-email {
    color: var(--black);
    word-break: break-all;
}

/* Opt-in modifier for the handful of agents whose addresses are long enough
   to wrap mid-domain inside the button on phones (Carl, Philip, Dawn, Angie).
   Applied per-page in HTML rather than universally so short addresses keep
   their default 1rem on mobile. Single-line + ellipsis as the safety net. */
@media (max-width: 768px) {
    .agent-email-long {
        font-size: 0.75rem;
        white-space: nowrap;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}

.agent-hero-trust {
    color: var(--gray-muted);
    font-size: 0.88rem;
    margin-top: 12px;
}

.agent-bio-section {
    background: var(--white);
}

.agent-bio {
    max-width: 760px;
    margin: 0 auto;
}

.agent-bio h2 {
    font-family: var(--font-heading);
    font-size: clamp(1.5rem, 2.5vw, 1.8rem);
    font-weight: 600;
    color: var(--black);
}

.agent-bio p {
    font-size: 1rem;
    line-height: 1.8;
    color: var(--gray-text);
    margin-top: 1.1em;
}




.agent-meta-heading {
    font-family: var(--font-heading);
    font-size: clamp(1.5rem, 2.5vw, 1.8rem);
    font-weight: 600;
    color: var(--black);
}

/* Center the bio + specialties section headings and their gold accent
   lines on ALL viewports. Both selectors are shared by every agent bio
   page, so this one block covers all 15 — desktop and mobile. */
.agent-bio h2,
.agent-meta-heading {
    text-align: center;
}

.agent-bio .gold-line-left,
.agent-specialties-section .gold-line-left {
    margin-left: auto;
}

.agent-meta-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 32px;
    margin-top: 32px;
}

.agent-meta-grid h3 {
    font-family: var(--font-body);
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--gold-text);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: 16px;
}

.agent-tag-list {
    list-style: none;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.agent-tag-list li {
    background: var(--white);
    border: 1px solid var(--gray-light);
    color: var(--gray-text);
    font-size: 0.92rem;
    padding: 6px 14px;
    border-radius: 999px;
}

.cta-inline-link {
    color: var(--gold);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 3px;
}

.cta-inline-link:hover {
    color: var(--white);
}

@media (min-width: 768px) {
    .agent-hero-grid {
        grid-template-columns: minmax(0, 480px) 1fr;
        align-items: start;
        gap: 56px;
    }

    .agent-hero-photo {
        margin: 0;
    }

    .agent-hero-meta {
        text-align: left;
    }

    .agent-hero-tags {
        justify-content: flex-start;
    }

    .agent-hero-cta {
        justify-content: flex-start;
    }

    .agent-meta-grid {
        grid-template-columns: 1fr 1fr;
    }
}

.agent-contact-icon {
    font-size: 1rem;
}

/* ---------- Join Our Team ---------- */
.join-team {
    background: var(--gray-bg);
}

.join-team-content {
    text-align: center;
    max-width: 680px;
    margin: 0 auto;
}

.join-team-content h2 {
    font-family: var(--font-heading);
    font-size: clamp(1.8rem, 3.5vw, 2.4rem);
    font-weight: 600;
    color: var(--black);
}

.join-team-content p {
    font-size: 1rem;
    color: var(--gray-text);
    line-height: 1.7;
    margin: 24px 0 36px;
}

/* ---------- Page Header ---------- */
.page-header {
    background: var(--black);
    padding: 100px 0 56px;
    margin-top: 108px;
    text-align: center;
}

.page-header h1 {
    font-family: var(--font-heading);
    font-size: clamp(2rem, 4vw, 2.8rem);
    font-weight: 700;
    color: var(--white);
    margin-bottom: 12px;
    /* Balance the heading across lines so no single word (e.g. "Estate" on
       the long Contact h1) is stranded alone. Falls back to normal wrapping
       on browsers without text-wrap support. */
    text-wrap: balance;
}

/* Karen's brand red on the page-level descriptor under the H1. The red
   is paired with a yellow .gold-line accent below (added to each
   .page-header in the markup) — that red+yellow pairing matches the
   flag motif Karen uses across her Facebook ads and print materials,
   and resolves the "isolated red reads as warning" problem. We briefly
   tried a darker muted red (#B91C1C) but its contrast against #1A1A1A
   was actually worse than #DC2626, so we returned to the brighter brand
   value and let the gold-line carry the softening role.
   .page-header is used only on listings/team/sell/contact (verified
   via grep) so this rule does not bleed into agent detail pages, which
   lead with .agent-breadcrumb instead. */
.page-header p {
    font-size: 1rem;
    color: var(--red);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
    font-weight: 300;
}

/* Color swap modifier — Karen flagged the red-on-black subtitle as
   hard to read (red #DC2626 on black #1A1A1A is ~4:1, borderline
   for WCAG AA on normal text and harder for older eyes). Adding
   `page-header-accent-swap` to the section moves the subtitle to
   sunshine yellow (~17:1 on black) and shifts the red accent onto
   the underline bar so the hero still carries the brand red+yellow
   flag motif.

   Subtitle is also bumped from font-weight 300 / 1rem to weight 500
   / 1.2rem — the higher contrast alone still felt visually light
   against the bold serif headline above it. Medium weight (not
   full bold) preserves the visual hierarchy: white serif H1 stays
   primary, gold subtitle reads as supporting copy.

   Applied on every page that uses .page-header (listings, team,
   sell, contact). The unmodified .page-header rule above stays as
   a forward-compatible fallback for any future page that wants the
   original red-on-black treatment. */
.page-header-accent-swap p {
    color: var(--gold);
    font-size: 1.2rem;
    font-weight: 500;
}
.page-header-accent-swap .gold-line {
    background:#dc2626;
}

/* ---------- Sell Page: Value Proposition ---------- */
.sell-value-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 56px;
    align-items: center;
}

.sell-value-text h2 {
    font-family: var(--font-heading);
    font-size: clamp(1.8rem, 3.5vw, 2.4rem);
    font-weight: 600;
    color: var(--black);
    margin-bottom: 0;
}

.sell-value-text p {
    font-size: 1rem;
    color: var(--gray-text);
    line-height: 1.8;
    margin-top: 24px;
}

.sell-value-prop h2 {
    color: var(--red);
}

.sell-benefits {
    margin-top: 24px;
    margin-bottom: 36px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.sell-benefits li {
    font-size: 0.95rem;
    color: var(--gray-text);
    line-height: 1.7;
    padding-left: 20px;
    position: relative;
}

.sell-benefits li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 10px;
    width: 8px;
    height: 8px;
    background: var(--gold);
    border-radius: 50%;
}

.sell-benefits li strong {
    color: var(--black);
}

.sell-value-image {
    width: 100%;
    border-radius: 8px;
    overflow: hidden;
    box-shadow: var(--shadow-lg);
}

.sell-value-image img {
    display: block;
    width: 100%;
    height: auto;
}

.brown-ln-banner {
    width: 100%;
    padding: 0;
    margin: 0;
    line-height: 0;
    overflow: hidden;
}

.brown-ln-banner img {
    display: block;
    width: 100%;
    height: auto;
    object-fit: cover;
}

/* ---------- Sell Page: Process Steps ---------- */
.process-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 32px;
}

.process-step {
    text-align: center;
    padding: 32px 20px;
    background: var(--white);
    border-radius: var(--radius);
    transition: transform var(--transition), box-shadow var(--transition);
}

.process-step:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow);
}

.process-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: var(--gold);
    color: var(--black);
    font-family: var(--font-heading);
    font-size: 1.4rem;
    font-weight: 700;
    margin-bottom: 20px;
}

.process-step h3 {
    font-family: var(--font-heading);
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--black);
    margin-bottom: 12px;
}

.process-step p {
    font-size: 0.88rem;
    color: var(--gray-text);
    line-height: 1.7;
}

/* ---------- Sell Page: Valuation Form ---------- */
.sell-form-subtitle {
    font-size: 1rem;
    color: var(--gray-muted);
    margin-top: 16px;
    max-width: 600px;
    margin-left: auto;
    margin-right: auto;
}

.valuation-form {
    max-width: 720px;
    margin: 0 auto;
}

.form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.form-group-full {
    grid-column: 1 / -1;
}

.form-label {
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--gray-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 6px;
}

.form-input {
    width: 100%;
    padding: 14px 16px;
    font-family: var(--font-body);
    font-size: 16px;
    color: var(--gray-text);
    background: var(--white);
    border: 1px solid var(--gray-light);
    border-radius: var(--radius);
    transition: border-color var(--transition), box-shadow var(--transition);
}

.form-input::placeholder {
    color: var(--gray-muted);
    opacity: 0.6;
}

.form-input:focus {
    outline: none;
    border-color: var(--gold);
    box-shadow: 0 0 0 3px rgba(255, 215, 0, 0.15);
}

.form-select {
    cursor: pointer;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23888' d='M1.41 0L6 4.58 10.59 0 12 1.41l-6 6-6-6z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    padding-right: 36px;
}

.form-textarea {
    resize: vertical;
    min-height: 100px;
}

.form-submit {
    text-align: center;
    margin-top: 32px;
}

.form-trust {
    font-size: 0.82rem;
    color: var(--gray-muted);
    margin-top: 14px;
    font-style: italic;
}

/* ---------- Contact Page: Two-Column Layout ---------- */
.contact-grid {
    display: grid;
    grid-template-columns: 1.2fr 1fr;
    gap: 56px;
    align-items: start;
}

/* Offset anchor targets so the fixed nav/trust bars don't cover the
   heading when the browser scrolls to it. Applied to every section
   heading we link to from CTAs. */
#contact-form,
#valuationForm {
    scroll-margin-top: 100px;
}

/* Mobile-only: the tour form success message needs extra top offset
   because the success element sits high in its section and would
   otherwise get hidden behind the fixed nav + trust bar. */
@media (max-width: 768px) {
    #tourSuccessMessage,
    .tour-success {
        scroll-margin-top: 150px;
    }
}

.contact-form-col h2 {
    font-family: var(--font-heading);
    font-size: clamp(1.8rem, 3.5vw, 2.4rem);
    font-weight: 600;
    color: var(--black);
    margin-bottom: 0;
}

.contact-form-col .gold-line {
    margin: 16px 0 0;
}

.contact-form {
    margin-top: 32px;
}

/* ---------- Contact Page: Info Card ---------- */
.contact-info-card {
    background: var(--white);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 36px;
}

.contact-info-card h3 {
    font-family: var(--font-heading);
    font-size: 1.3rem;
    font-weight: 600;
    color: var(--black);
    margin-bottom: 28px;
}

.contact-info-item {
    display: flex;
    gap: 16px;
    align-items: flex-start;
    padding: 16px 0;
    border-bottom: 1px solid var(--gray-light);
}

.contact-info-item:last-of-type {
    border-bottom: none;
}

.contact-info-icon {
    font-size: 1.3rem;
    line-height: 1.4;
    flex-shrink: 0;
    width: 28px;
    text-align: center;
}

.contact-info-label {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--gray-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 4px;
}

.contact-info-value {
    font-size: 0.92rem;
    color: var(--gray-text);
    line-height: 1.6;
}

.contact-info-link {
    color: var(--black);
    font-weight: 600;
    transition: color var(--transition);
}

.contact-info-link:hover {
    color: var(--gold);
}

/* ---------- Contact Page: Locked Map + GBP Click Overlay ----------
   The Google Maps iframe is set to pointer-events: none so users can't
   accidentally drag or zoom on mobile. A transparent <a> sits on top
   and redirects any click/tap to our Google Business Profile in a new
   tab — Google traffic to the GBP page strengthens our local SEO ranking
   signals (visit rate is a known LocalBusiness ranking factor). */
.contact-map-wrap {
    position: relative;
    width: 100%;
    height: 250px;
    border-radius: 8px;
    overflow: hidden;
    margin-top: 24px;
}

.contact-map {
    pointer-events: none;
    display: block;
    width: 100%;
    height: 100%;
}

.contact-map-link {
    position: absolute;
    inset: 0;
    display: block;
    cursor: pointer;
    background: transparent;
    transition: background var(--transition);
}

.contact-map-link:hover,
.contact-map-link:focus-visible {
    background: rgba(26, 26, 26, 0.06);
    outline: none;
}

/* ---------- Contact Page: Map Placeholder ---------- */
.map-placeholder {
    width: 100%;
    height: 280px;
    background: var(--gray-bg);
    border-radius: var(--radius);
    margin-top: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--gray-muted);
    border: 1px dashed var(--gray-light);
}

/* ---------- Contact Page: Quick-Call Banner ---------- */
.quick-call-banner {
    background: var(--black);
    padding: 40px 0;
}

.quick-call-content {
    text-align: center;
}

.quick-call-content p {
    font-family: var(--font-heading);
    font-size: clamp(1.1rem, 2.5vw, 1.5rem);
    font-weight: 500;
    color: var(--white);
}

.quick-call-number {
    color: var(--gold);
    font-weight: 700;
    transition: color var(--transition);
}

.quick-call-number:hover {
    color: var(--gold-dark);
}

/* ---------- Contact Page: Service Areas ---------- */
.areas-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 28px;
}

.area-card {
    background: var(--white);
    border: 1px solid var(--black);
    border-radius: var(--radius);
    padding: 28px;
    box-shadow: var(--shadow);
    transition: transform var(--transition), box-shadow var(--transition);
}

.area-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-lg);
}

.area-card h3 {
    font-family: var(--font-heading);
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--black);
    margin-bottom: 12px;
    padding-bottom: 12px;
    border-bottom: 2px solid var(--gold);
}

.area-card ul li {
    font-size: 0.9rem;
    color: var(--gray-text);
    padding: 5px 0;
    padding-left: 16px;
    position: relative;
}

.area-card ul li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 13px;
    width: 6px;
    height: 6px;
    background: var(--gold);
    border-radius: 50%;
}

/* ---------- Contact Page: Value Proposition Section ----------
   Trust-building value-prop block between the dark "Prefer to talk?"
   banner and the white service-areas section. Background flow: dark
   banner → gray (this section) → white (Proudly Serving) → dark CTA,
   creating a stepped contrast between the two adjacent light sections
   instead of letting them blur together. H2 reuses the page's shared
   .section-header + .gold-line pattern so its underline accent matches
   "Send Us a Message," "Get in Touch Directly," and "Proudly Serving
   Southeast Missouri." The copy column caps at 760px so the four
   paragraphs read at a comfortable line length on desktop.

   Bottom padding is trimmed (and the Proudly Serving section's top
   padding is trimmed in lockstep below) to halve the inter-section
   gap from 192px → 96px on desktop / 144px → 72px on mobile, so the
   two related-content blocks read as a connected pair instead of
   floating apart.

   NOTE: scoped to .contact-value-prop (not .why-choose) so the padding
   overrides don't bleed into the homepage's pre-existing .why-choose
   "Why Choose Us" feature-cards section, which uses the same English
   label but is a different layout. */
.contact-value-prop {
    padding-bottom: 48px;
}

.service-areas {
    padding-top: 48px;
}

.contact-value-prop-copy {
    max-width: 760px;
    margin: 0 auto;
    text-align: center;
}

.contact-value-prop-copy p {
    font-family: var(--font-body);
    font-size: 1.05rem;
    line-height: 1.8;
    color: var(--gray-text);
}

.contact-value-prop-copy p + p {
    margin-top: 20px;
}

/* ---------- Responsive ---------- */
@media (max-width: 1024px) {
    .listings-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .footer-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .sell-value-grid {
        grid-template-columns: 1fr;
        gap: 40px;
    }

    .sell-value-image {
        max-width: 100%;
    }

    .process-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .areas-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    /* Hamburger collapse moved up from 768px to 1024px. Why: the larger
       senior-readability nav typography (1.125rem links + 1.85rem brand +
       1.125rem CTA) overflows the desktop nav bar at 1024–1100px viewports.
       Erring on the side of "bigger links, earlier hamburger" — the hamburger
       drawer is already touch-friendly and inherits the same larger sizing
       so senior users get the same readable links there too. */
    .mobile-toggle {
        display: flex;
    }

    /* Home-page mobile: pin hamburger to the right since there's no brand in the bar */
    .navbar-home .nav-container {
        justify-content: flex-end;
    }

    .navbar-home .nav-right {
        flex: initial;
    }

    /* Mobile-opened nav on home: restore vertical stacked menu (overrides desktop centered row) */
    .navbar-home .nav-right.open .nav-links {
        gap: 16px;
    }

    .nav-right {
        display: none;
        position: absolute;
        top: 76px;
        left: 0;
        width: 100%;
        background: var(--black);
        flex-direction: column;
        padding: 24px;
        gap: 24px;
        border-top: 1px solid rgba(255, 255, 255, 0.1);
    }

    .nav-right.open {
        display: flex;
    }

    .nav-links {
        flex-direction: column;
        gap: 16px;
    }

    .nav-cta {
        align-self: center;
    }
}

@media (max-width: 768px) {
    /* Logo continues to shrink at the narrower 768px breakpoint — the
       hamburger transition itself moved up to 1024px (see block above),
       but a 50px logo still feels oversized on phone-width screens. */
    .nav-logo {
        height: 40px;
    }

    /* Hero brand gets a tighter gap above the h1 on smaller screens */
    .hero-brand {
        margin-bottom: 18px;
    }

    .filter-bar {
        flex-direction: column;
    }

    .filter-group {
        min-width: 100%;
    }

    .filter-btn {
        width: 100%;
    }

    .results-toolbar {
        flex-direction: column;
        gap: 12px;
        align-items: flex-start;
    }

    .sort-select {
        width: 100%;
    }

    .stats-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 32px;
    }

    .listings-grid {
        grid-template-columns: 1fr;
        max-width: 480px;
        margin: 0 auto;
    }

    .features-grid {
        grid-template-columns: 1fr;
        gap: 20px;
    }

    .section {
        padding: 72px 0;
    }

    /* Mirror the desktop override: tighter listings-to-Recently-Sold
       gap so the social-proof section is within scroll-and-glance
       reach of the last listing card on small viewports. ~44px
       combined gap (22 + 22) sits inside the user-spec target of
       40-50px for <768px breakpoints. */
    .listings-results {
        padding-bottom: 22px;
    }
    .recently-sold-section {
        padding-top: 22px;
    }

    .footer-grid {
        grid-template-columns: 1fr;
        gap: 36px;
    }

    .footer-bottom-inner {
        flex-direction: column;
        gap: 8px;
        text-align: center;
    }

    .cta-section {
        padding: 72px 0;
    }

    .process-grid {
        grid-template-columns: 1fr;
        max-width: 480px;
        margin: 0 auto;
    }

    .form-grid {
        grid-template-columns: 1fr;
    }

    .contact-grid {
        grid-template-columns: 1fr;
        gap: 40px;
    }

    .areas-grid {
        grid-template-columns: 1fr;
        max-width: 400px;
        margin: 0 auto;
    }

    .contact-value-prop-copy p {
        font-size: 1rem;
        line-height: 1.75;
    }

    /* Scale the tightened inter-section gap proportionally with the
       72px mobile .section padding so the value-prop / service-areas
       pair stays connected at narrow viewports too. */
    .contact-value-prop {
        padding-bottom: 36px;
    }

    .service-areas {
        padding-top: 36px;
    }
}

@media (max-width: 480px) {
    /* Brand bumps proportionally on tiny screens (1.1 → 1.3rem ≈ 21px)
       but stays smaller than the desktop value so "Delta Realty, LLC"
       doesn't crowd the hamburger toggle on 320–360px viewports. */
    .nav-brand-text {
        font-size: 1.3rem;
    }

    .hero-brand {
        margin-bottom: 14px;
    }

    .stats-grid {
        grid-template-columns: 1fr;
    }

    .hero-buttons {
        flex-direction: column;
        align-items: center;
    }

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

    .hero-content h1 {
        font-size: 1.8rem;
    }

    .contact-value-prop-copy p {
        font-size: 0.95rem;
        line-height: 1.7;
    }

    .contact-value-prop-copy p + p {
        margin-top: 16px;
    }
}

/* ---------- Form Validation States ---------- */
/* These styles support client-side validation feedback. The error
   state uses a red border + message to clearly indicate which field
   needs attention. The success state replaces the entire form with
   a confirmation message. Both use transitions to avoid jarring
   visual jumps. */

.field-error {
    border-color: #D32F2F !important;
    box-shadow: 0 0 0 3px rgba(211, 47, 47, 0.12) !important;
}

.error-message {
    display: block;
    font-size: 0.78rem;
    font-weight: 500;
    color: #D32F2F;
    margin-top: 6px;
    animation: errorAppear 0.25s ease;
}

@keyframes errorAppear {
    from {
        opacity: 0;
        transform: translateY(-4px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.form-success {
    text-align: center;
    padding: 64px 24px;
    animation: successAppear 0.4s ease;
}

@keyframes successAppear {
    from {
        opacity: 0;
        transform: scale(0.95);
    }
    to {
        opacity: 1;
        transform: scale(1);
    }
}

.form-success-icon {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: #2E7D32;
    margin: 0 auto 24px;
    position: relative;
}

.form-success-icon::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 20px;
    height: 10px;
    border-left: 3px solid var(--white);
    border-bottom: 3px solid var(--white);
    transform: translate(-50%, -60%) rotate(-45deg);
}

.form-success-text {
    font-family: var(--font-heading);
    font-size: clamp(1.05rem, 2vw, 1.3rem);
    font-weight: 500;
    color: var(--gray-text);
    line-height: 1.7;
    max-width: 480px;
    margin: 0 auto;
}

.form-success-detail {
    font-size: 0.85rem;
    color: #999;
    margin-top: 1rem;
    font-style: italic;
}

/* ---------- Micro-Interactions ---------- */
/* Smooth transition on submit buttons so disabled state change
   doesn't feel jarring — the color shift animates instead of snapping */
.btn {
    transition: all 0.2s ease;
}

/* Form field focus — gold glow matches brand, meets WCAG 2.4.7
   Focus Visible requirement. The 3px ring ensures keyboard-only
   users can always see which field is active. */
.form-input:focus,
.filter-select:focus {
    outline: none;
    border-color: var(--gold);
    box-shadow: 0 0 0 3px rgba(255, 215, 0, 0.2);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

/* --- Review CTA Section --- */
.review-cta {
    background: var(--black);
    color: var(--white);
    text-align: center;
    padding: 60px 0;
}

.review-cta h2 {
    color: var(--gold);
    font-family: var(--font-heading);
    font-size: clamp(1.75rem, 4vw, 2.5rem);
    margin: 0 0 16px;
}

.review-cta p {
    color: var(--gray-light, #ccc);
    font-size: 1.1rem;
    max-width: 640px;
    margin: 0 auto 32px;
    line-height: 1.6;
}

.review-cta .btn-gold {
    display: inline-block;
}

@media (max-width: 480px) {
    .review-cta {
        padding: 48px 0;
    }
    .review-cta p {
        font-size: 1rem;
    }
}

/* Soft review ask appended to form success messages */
.form-success-review {
    margin-top: 16px;
    font-size: 0.95rem;
    color: var(--gray-text, #555);
}

.form-success-review a {
    color: var(--gold);
    font-weight: 600;
    text-decoration: underline;
}

/* --- Admin Panel --- */
.admin-body {
    background: var(--black);
    min-height: 100vh;
    margin: 0;
    font-family: var(--font-body);
}

.admin-container {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;
}

.admin-card {
    background: var(--white);
    border-radius: 8px;
    padding: 48px 40px;
    width: 100%;
    max-width: 420px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.4);
    text-align: center;
}

.admin-card-wide {
    max-width: 560px;
    text-align: left;
}

.admin-brand {
    font-family: var(--font-heading);
    color: var(--black);
    font-size: 1.75rem;
    margin: 0 0 4px;
    text-align: center;
}

.admin-brand span {
    color: var(--gold);
}

.admin-subtitle {
    color: var(--gray-text, #666);
    font-size: 0.95rem;
    margin: 0 0 32px;
    text-align: center;
}

.admin-form {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.admin-form label {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--black);
    margin-top: 14px;
}

.admin-form input,
.admin-form select {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 1rem;
    font-family: inherit;
    box-sizing: border-box;
    background: var(--white);
}

.admin-form input:focus,
.admin-form select:focus {
    outline: none;
    border-color: var(--gold);
    box-shadow: 0 0 0 3px rgba(255, 215, 0, 0.2);
}

.admin-submit {
    margin-top: 24px;
    width: 100%;
}

.admin-error {
    margin: 16px 0 0;
    padding: 10px 14px;
    background: #fdecea;
    color: #a32e22;
    border-radius: 4px;
    font-size: 0.9rem;
}

.admin-message {
    margin: 18px 0 0;
    padding: 12px 14px;
    border-radius: 4px;
    font-size: 0.95rem;
}

.admin-message-success {
    background: #e8f5ee;
    color: #1f7a3d;
    border-left: 3px solid #1f7a3d;
}

.admin-message-error {
    background: #fdecea;
    color: #a32e22;
    border-left: 3px solid #a32e22;
}

.admin-counter {
    margin-top: 24px;
    text-align: center;
    color: var(--gray-text, #666);
    font-size: 0.9rem;
}

.admin-counter #sentCount {
    color: var(--gold);
    font-weight: 700;
}

@media (max-width: 480px) {
    .admin-card {
        padding: 32px 24px;
    }
}

/* ==========================================================
   Sticky Mobile CTA Bar
   Mobile-only fixed bottom bar with Call Now / Email Us.
   Hidden on desktop (display: none). On <=768px viewports it
   becomes a fixed flex row pinned to the bottom of the viewport.
   env(safe-area-inset-bottom) adds padding on iPhones with the
   home-indicator bar so the buttons clear the gesture area.
   body padding-bottom keeps page content from being covered.
   ========================================================== */

.mobile-cta-bar {
    display: none;
}

@media (max-width: 768px) {
    .mobile-cta-bar {
        display: flex;
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 9999;
        background: #1A1A1A;
        border-top: 2px solid #FFD700;
        padding: 10px 16px;
        padding-bottom: calc(10px + env(safe-area-inset-bottom));
        gap: 12px;
    }

    /* Hide while a form input is focused — keeps the bar from following the
       iOS soft keyboard up and sitting on top of the form. body.dr-input-focused
       is toggled by a focusin/focusout listener in the wrapper template.
       !important wins against the display: flex above and any inline-style
       edge cases (IDX-injected forms include this rule's match via the body
       class, not the bar element, so no IDX coupling). */
    body.dr-input-focused .mobile-cta-bar {
        display: none !important;
    }

    .mobile-cta-btn {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 6px;
        padding: 10px 12px;
        border-radius: 8px;
        font-family: 'Inter', sans-serif;
        font-size: 14px;
        font-weight: 600;
        text-decoration: none;
        transition: opacity 0.2s;
    }

    .mobile-cta-btn:active {
        opacity: 0.8;
    }

    .mobile-cta-call {
        background: #FFD700;
        color: #1A1A1A;
    }

    .mobile-cta-email {
        background: transparent;
        color: #FFD700;
        border: 2px solid #FFD700;
    }

    /* Push page content up so the fixed bar doesn't cover the footer */
    body {
        padding-bottom: 80px;
    }

    footer {
        margin-bottom: 0;
    }
}

/* ==========================================================================
   HERO SCROLL INDICATOR — fold-mystery UX fix
   ==========================================================================
   When a hero is `height: 100vh`, visitors on touch / trackpad devices
   (where the scrollbar is hidden until interaction) can mistake the hero
   for the entire page and bounce. A subtle animated chevron at the bottom
   edge signals "more below," recovering would-be bounces. The bounce
   animation is constrained (6px lift) so it reads as a hint, not a
   distraction competing with the primary CTAs above it.
   ========================================================================== */

.hero-scroll-indicator {
    position: absolute;
    bottom: 28px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    color: var(--gold);
    text-decoration: none;
    z-index: 2;
    padding: 8px 14px;
    border-radius: var(--radius);
    /* transform is animated so the hover scale eases in. translateX(-50%)
       must be re-applied alongside scale() in the hover rule, otherwise
       the indicator jumps off-center when the transform is replaced. */
    transition: opacity 0.4s ease, color 0.2s ease, transform 0.2s ease;
}

/* JS adds .is-hidden via IntersectionObserver once the user has scrolled
   past the hero. pointer-events: none prevents the invisible link from
   intercepting clicks on content below. */
.hero-scroll-indicator.is-hidden {
    opacity: 0;
    pointer-events: none;
}

.hero-scroll-label {
    font-family: var(--font-body);
    /* Sized up ~20% from the original 0.75rem for low-vision senior
       readability (Karen's audience). Bold weight + generous tracking
       further lifts the silhouette against the dark hero photo. */
    font-size: 0.9rem;
    font-weight: 700;
    letter-spacing: 2px;
    text-transform: uppercase;
    /* Brand gold at full opacity. WCAG AA: #FFD700 on the hero overlay
       (linear-gradient 50–80% black over the photo) yields >12:1 contrast
       against the darkest band and ~8:1 against typical photo midtones —
       comfortably above the 4.5:1 normal-text floor. The text-shadow
       below is belt-and-suspenders for the rare hero photo region where
       the overlay sits over a near-white pixel (sky, porch highlight). */
    color: var(--gold);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    transition: color 0.2s ease;
}

.hero-scroll-chevron {
    color: var(--gold);
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
    animation: heroScrollBounce 1.8s ease-in-out infinite;
    /* Color and animation-duration both transition so the hover-driven
       darken + speed-up land smoothly together, not in a snap. */
    transition: color 0.2s ease;
}

/* Hover — "intensify" pattern. The element grows (scale 1.1), the gold
   deepens to gold-dark (matches the existing button-hover language at
   .btn-gold:hover), and the bounce roughly doubles in tempo. The element
   stays clearly visible throughout — no fade, no near-black drift. */
.hero-scroll-indicator:hover {
    transform: translateX(-50%) scale(1.1);
}

.hero-scroll-indicator:hover .hero-scroll-label,
.hero-scroll-indicator:hover .hero-scroll-chevron {
    color: var(--gold-dark);
}

.hero-scroll-indicator:hover .hero-scroll-chevron {
    animation-duration: 0.9s;
}

/* WCAG 2.4.7 Focus Visible — keyboard users must see a clear focus state.
   :focus-visible suppresses the outline on mouse clicks while keeping it
   for keyboard tab navigation. */
.hero-scroll-indicator:focus-visible {
    outline: 2px solid var(--gold);
    outline-offset: 4px;
}

@keyframes heroScrollBounce {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(6px); }
}

/* Respect users with motion sensitivity or OS-level "reduce motion" set.
   The indicator stays visible (it still serves the fold-mystery purpose)
   but every motion effect freezes: bounce, hover scale, and hover bounce
   speed-up. Color hover is preserved — color shifts aren't motion. */
@media (prefers-reduced-motion: reduce) {
    .hero-scroll-chevron,
    .hero-scroll-indicator:hover .hero-scroll-chevron {
        animation: none;
    }
    .hero-scroll-indicator,
    .hero-scroll-indicator:hover {
        transition: opacity 0.2s linear, color 0.2s linear;
        transform: translateX(-50%);
    }
}

/* Tablet — pull tighter to the hero edge and shrink the label/chevron
   proportionally. Sizes scale with the same ~20% senior-readability bump
   applied at desktop so the indicator stays legible on phones in hand. */
@media (max-width: 768px) {
    .hero-scroll-indicator {
        bottom: 18px;
        gap: 4px;
        padding: 6px 12px;
    }
    .hero-scroll-label {
        font-size: 0.85rem;
        letter-spacing: 1.6px;
    }
    .hero-scroll-chevron {
        width: 22px;
        height: 22px;
    }
}

/* Mobile — under 480px the hero buttons stack vertically (see line 2278),
   which uses extra hero height. Keeping the indicator tucked tight prevents
   any overlap with the second stacked button while preserving readability. */
@media (max-width: 480px) {
    .hero-scroll-indicator {
        bottom: 14px;
    }
    .hero-scroll-label {
        font-size: 0.8rem;
        letter-spacing: 1.4px;
    }
    .hero-scroll-chevron {
        width: 20px;
        height: 20px;
    }
}

/* ==========================================================
   LISTING DETAIL PAGES
   Generated by scripts/build_detail_pages.py from
   templates/listing-detail.html. Every rule is scoped under
   `.detail-*` (or to children of those wrappers) so nothing
   here can leak back into the homepage / listings grid.
   ========================================================== */

/* Back-to-listings link — single-line nav above the hero. margin-top
   clears the fixed trust-bar (32px) + navbar (76px) so the link isn't
   hidden behind the header. Same 108px offset used by .page-header
   across the rest of the site so the visual baseline matches.

   Color: black default for high contrast against the white nav strip
   (sunshine-yellow on white failed WCAG contrast guidelines and was
   genuinely hard to read). The arrow + label transition together to
   sunshine-yellow on hover/focus to preserve the brand-color
   interaction signal. */
.detail-back-nav {
    margin-top: 108px;
    background: var(--white);
    padding: 16px 0;
}
.detail-back-link {
    display: inline-block;
    font-family: var(--font-body);
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--black);
    text-decoration: none;
    letter-spacing: normal;
    transition: color 0.2s ease;
}
.detail-back-link:hover,
.detail-back-link:focus-visible {
    color: var(--gold);
    text-decoration: underline;
    outline: none;
}

.detail-hero {
    /* Generous top padding gives the hero photo + status badges (top-left
       inside the photo) breathing room below the fixed nav. Without this,
       the badge sat too close to the navbar bottom on desktop and was
       outright clipped by the navbar on mobile portrait viewports. */
    padding: 56px 0 64px;
    background: var(--white);
}
.detail-hero-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    gap: 40px;
    /* `align-items: start` lets the photo container size itself by its
       own aspect-ratio independently of the right summary column's
       height. On Residential/Commercial listings the right column has
       more content (more quick stats, longer address); with `stretch`
       (the grid default) the photo container was being pulled taller
       than its 4:3 ratio and the inner img with object-fit: cover was
       overflowing visually. `start` pins the photo to its preferred
       aspect ratio and lets the right column extend below if needed. */
    align-items: start;
}
.detail-hero-photo {
    position: relative;
    /* 1px black border + var(--radius) corners mirror the .property-card
       treatment on listings.html, so the hero photo reads as the same
       visual object as the card the user just clicked from. Gallery
       thumbnails intentionally stay borderless — only the hero gets
       the listing-card frame. */
    border: 1px solid var(--black);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--black);
    box-shadow: var(--shadow);
    /* 4:3 reads cleaner across mixed inventory than the previous 3:2 —
       Karen's photographer tends to shoot wider exterior shots that lose
       the front porch in 3:2 cropping. max-height is a safety net so
       the photo can't get absurdly tall on ultra-wide viewports. */
    aspect-ratio: 4 / 3;
    max-height: 600px;
    width: 100%;
}
.detail-hero-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.4s ease;
}
.detail-hero-photo:hover img {
    transform: scale(1.02);
}
.detail-hero-badge {
    position: absolute;
    top: 16px;
    left: 16px;
    z-index: 2;
}
.detail-hero-summary {
    display: flex;
    flex-direction: column;
    justify-content: center;
}
/* Price pillow — mirrors the .property-price treatment on the listings
   cards so the price reads as the same brand element across the site:
   sunshine yellow (var(--gold)) background with black text inside a
   black-bordered rounded pill. width: fit-content overrides the
   default flex cross-axis stretch from .detail-hero-summary, so the
   pillow hugs the price string regardless of digit count instead of
   filling the summary column. */
.detail-price {
    font-family: var(--font-heading);
    color: var(--black);
    background: var(--gold);
    border: 2px solid var(--black);
    border-radius: 8px;
    display: inline-block;
    width: fit-content;
    max-width: 100%;
    padding: 4px 18px;
    font-size: clamp(1.6rem, 3.4vw, 2.2rem);
    font-weight: 700;
    margin: 0 0 14px;
    line-height: 1.1;
}
.detail-address {
    font-family: var(--font-heading);
    color: var(--black);
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 600;
    margin: 0 0 8px;
    line-height: 1.2;
}
/* Playfair Display ships with old-style figures (the `onum` OpenType
   feature) as its default — digits like 0/1/2 sit at x-height while
   3/4/5/7/9 reach above or below the baseline. That reads fine when
   every digit is oldstyle together (e.g. "39988 Billy Blvd"), but a
   leading "0" in addresses like "0 State Highway 25" looks visibly
   shorter than the surrounding capital letters. The build script tags
   only those zero-prefixed addresses with this modifier class so they
   opt into lining figures (uniform cap-height digits), while every
   other address keeps the brand's default Playfair oldstyle look. */
.detail-address--lining-nums {
    font-variant-numeric: lining-nums;
    font-feature-settings: "lnum" 1;
}
.detail-locale {
    color: var(--gray-text);
    font-size: 1rem;
    margin: 0 0 24px;
}
.detail-quickstats {
    list-style: none;
    padding: 0;
    margin: 0 0 28px;
    display: grid;
    /* Locked to 3 columns at desktop/tablet so the placement of
       "Lot Size (Ft)" at column 2 below has a stable meaning across
       viewport widths. The mobile @max-480 rule below collapses to
       2 columns and disables the explicit col-2 placement so the FT
       cell flows naturally instead of orphaning a half-empty row. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
    border-top: 1px solid var(--gray-light);
    border-bottom: 1px solid var(--gray-light);
    padding-block: 18px;
}
.detail-quickstats li {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.detail-quickstats .qs-label {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--gray-muted);
    font-weight: 500;
}
.detail-quickstats .qs-value {
    font-family: var(--font-heading);
    font-size: 1.15rem;
    color: var(--black);
    font-weight: 600;
}
/* "Lot Size (Ft)" placement — when both lot fields are present, the
   build script emits ACRES inline and FT here so the cell pins to
   column 1 of the next row (vertically under YEAR BUILT on
   Residential). Left-anchored placement follows natural left-to-right
   reading flow; an earlier center-aligned position read as orphaned
   with empty cells on both sides. Build script only routes FT through
   this rule when len(quick_stats) is a multiple of 3 — i.e., when the
   natural flow would already put FT at column 1 of a fresh row.
   Singletons and dense layouts (e.g., Lot/Land "both" with only
   3 items total) flow inline above instead. */
.detail-quickstats .qs-lot-row {
    grid-column: 1 / 2;
}
.detail-cta-group {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}
.detail-cta-group .btn {
    flex: 1 1 auto;
    min-width: 200px;
    text-align: center;
}
/* Primary "I'm Interested" CTA — the .btn .btn-gold base supplies the
   sunshine-yellow fill; we layer a 2px black border on top so the button
   reads as a matched pair with the outlined Call button next to it.
   Both buttons are now the same silhouette: rounded rectangle, 2px black
   border, just filled vs outlined. text-transform/letter-spacing are
   reset explicitly so the "I'm" apostrophe renders with natural Inter
   kerning instead of an awkward gap between the I and the m (which can
   surface if any cascading rule applies tracking or uppercase). */
.detail-cta-primary {
    border: 2px solid var(--black);
    text-transform: none;
    letter-spacing: normal;
}
/* The secondary "Call ..." button is intentionally a matched pair with
   the primary "I'm Interested" button above it: same .btn .btn-lg
   typography + padding (16px / 1rem from .btn-lg), with the only visual
   difference being filled vs outlined. The earlier .btn-outline class
   doesn't exist in the project — this rule supplies that outlined look
   directly so the call button doesn't fall back to the unsized .btn
   default. */
.detail-cta-secondary {
    background: var(--white);
    color: var(--black);
    border: 2px solid var(--black);
    text-transform: none;
    letter-spacing: normal;
}
.detail-cta-secondary:hover {
    background: var(--black);
    color: var(--gold);
    border-color: var(--black);
    transform: translateY(-2px);
}
/* Bottom-CTA "I'm Interested" button — same letter-spacing/text-transform
   reset as the top CTA so the apostrophe in "I'm" renders cleanly in
   both placements. No black border here; the yellow-on-black contrast
   in .detail-bottom-cta already separates the button from its dark
   backdrop. */
.detail-bottom-cta .btn-gold {
    text-transform: none;
    letter-spacing: normal;
}

/* Sold treatment — desaturate the hero photo and add a subtle SOLD
   ribbon over the corner so visitors see the status before reading
   the badge. Bottom CTA copy gets swapped at build time. */
.detail-hero.is-sold .detail-hero-photo img {
    filter: grayscale(100%);
    opacity: 0.85;
}

/* Section heading reused across detail subsections — slightly smaller
   than the page-header H1 so the visual hierarchy reads top-down. */
.detail-section-heading {
    font-family: var(--font-heading);
    color: var(--black);
    font-size: clamp(1.4rem, 2.5vw, 1.8rem);
    font-weight: 600;
    text-align: center;
    margin: 0;
}
/* The page wraps prose in this narrow container so long descriptions
   stay readable (~70ch is the proven sweet spot). The wider sections
   (gallery, map) keep using the standard .container width. */
.detail-content-narrow {
    max-width: 820px;
}

/* Section rhythm — only Photo Gallery and Features get the light-gray
   backdrop. Two gray bands across the page (instead of alternating every
   section) breaks the monotony without feeling stripey. White space
   reads as the dominant rhythm; gray is the punctuation. The section
   wrapper carries the background so it extends edge-to-edge of the
   viewport, with the inner .container keeping content centered. */
.detail-gallery,
.detail-features {
    background: var(--gray-bg);
}
.detail-description,
.detail-details,
.detail-appliances,
.detail-map {
    background: var(--white);
}

/* Gallery thumbnails — single horizontal row that wraps to a grid
   on smaller viewports. Each thumb is a button so screen readers
   announce it as activatable. */
.gallery-thumbs {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 12px;
    margin-top: 32px;
}
.gallery-thumb {
    border: 0;
    padding: 0;
    background: var(--gray-bg);
    border-radius: var(--radius);
    overflow: hidden;
    cursor: pointer;
    aspect-ratio: 3 / 2;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.gallery-thumb:hover,
.gallery-thumb:focus-visible {
    transform: translateY(-2px);
    box-shadow: var(--shadow);
    outline: 2px solid var(--gold);
    outline-offset: 2px;
}
.gallery-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.detail-description-text {
    color: var(--gray-text);
    font-size: 1rem;
    line-height: 1.75;
    margin-top: 32px;
    white-space: pre-line;
}

.detail-features-grid {
    list-style: none;
    padding: 0;
    margin: 32px 0 0;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px 24px;
}
.detail-feature-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    color: var(--gray-text);
    font-size: 0.95rem;
    line-height: 1.5;
}
.detail-feature-check {
    color: var(--gold);
    flex-shrink: 0;
    margin-top: 2px;
}

.details-table {
    width: 100%;
    margin-top: 32px;
    border-collapse: collapse;
    border: 1px solid var(--gray-light);
}
.details-table tr:nth-child(odd) {
    background: var(--gray-bg);
}
.details-table th,
.details-table td {
    padding: 12px 16px;
    text-align: left;
    font-size: 0.95rem;
}
.details-table th {
    font-family: var(--font-body);
    color: var(--gray-muted);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    font-size: 0.78rem;
    width: 40%;
}
.details-table td {
    color: var(--black);
    font-weight: 500;
}

.detail-appliances-text {
    color: var(--gray-text);
    font-size: 1rem;
    line-height: 1.7;
    margin-top: 24px;
}

/* Map embed — locked iframe with a transparent <a> overlay that captures
   every click and opens the property's location in Google Maps proper.
   Same lock+click pattern as .contact-map-wrap on the contact page, kept
   visually consistent so users get one predictable behavior across the
   site (you don't pan our embedded map; tap it to get the real Maps app). */
.map-embed {
    position: relative;
    margin-top: 32px;
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow);
    aspect-ratio: 16 / 9;
    background: var(--gray-bg);
    cursor: pointer;
}
.map-embed iframe {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
    /* pointer-events: none is what enforces the lock — touch/mouse never
       reach Google's iframe, so the user can't accidentally pan or zoom
       it out of the property view on mobile. */
    pointer-events: none;
}
.map-embed-link {
    position: absolute;
    inset: 0;
    display: block;
    background: transparent;
    transition: background var(--transition);
}
.map-embed-link:hover,
.map-embed-link:focus-visible {
    /* Subtle dark wash on hover hints "this is clickable" without obscuring
       the map. Same intensity as .contact-map-link for visual consistency. */
    background: rgba(26, 26, 26, 0.06);
    outline: none;
}

.detail-bottom-cta {
    background: var(--black);
    color: var(--white);
    padding: 64px 0;
    text-align: center;
}
.detail-bottom-cta h2 {
    font-family: var(--font-heading);
    color: var(--white);
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 600;
    margin: 0 0 4px;
}
/* Sunshine-yellow accent rule between the question heading and the
   supporting paragraph — same .gold-line element used elsewhere on
   the page, just given a touch more bottom breathing room here so
   the rule doesn't crash into the paragraph. */
.detail-bottom-cta .gold-line {
    margin: 16px auto 24px;
}
.detail-bottom-cta p {
    color: rgba(255, 255, 255, 0.78);
    font-size: 1rem;
    line-height: 1.6;
    max-width: 540px;
    margin: 0 auto 24px;
}

/* Lightbox overlay — full-screen photo viewer. aria-hidden controls
   visibility; .is-open is the visual class so transitions hook in
   cleanly. */
.lightbox {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.92);
    z-index: 9999;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.lightbox.is-open {
    display: flex;
}
.lightbox-figure {
    margin: 0;
    max-width: min(1200px, 95vw);
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}
.lightbox-figure img {
    max-width: 100%;
    max-height: 80vh;
    object-fit: contain;
    box-shadow: 0 12px 48px rgba(0, 0, 0, 0.6);
}
.lightbox-caption {
    color: var(--white);
    font-size: 0.9rem;
    text-align: center;
    opacity: 0.8;
}
.lightbox-close,
.lightbox-nav {
    position: absolute;
    background: rgba(0, 0, 0, 0.55);
    color: var(--white);
    border: 1px solid rgba(255, 255, 255, 0.25);
    width: 48px;
    height: 48px;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.6rem;
    line-height: 1;
    transition: background 0.2s ease, border-color 0.2s ease;
}
.lightbox-close:hover,
.lightbox-close:focus-visible,
.lightbox-nav:hover,
.lightbox-nav:focus-visible {
    background: var(--gold);
    color: var(--black);
    border-color: var(--gold);
    outline: none;
}
.lightbox-close {
    top: 20px;
    right: 20px;
    font-size: 2rem;
}
.lightbox-prev {
    left: 20px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 2rem;
}
.lightbox-next {
    right: 20px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 2rem;
}

/* The detail page already has its own bottom-CTA block, so the
   sticky bar surfaces "Ask About This Property" instead of "Get
   Answers" — rendered with the same .mobile-cta-bar shell so the
   styling continues to live in one place. */
.mobile-cta-bar-detail .mobile-cta-email {
    /* Inherits all the existing .mobile-cta-email styling. Hook for
       future tweaks (e.g., red urgency variant on stale listings). */
}

/* ---------- Detail responsive ---------- */
@media (max-width: 1024px) {
    .detail-hero-grid {
        grid-template-columns: 1fr;
        gap: 32px;
    }
    .detail-features-grid {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 768px) {
    .detail-hero {
        padding: 32px 0 48px;
    }
    .detail-cta-group .btn {
        width: 100%;
    }
    .gallery-thumbs {
        grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
        gap: 8px;
    }
    .details-table th,
    .details-table td {
        padding: 10px 12px;
        font-size: 0.9rem;
    }
    .lightbox-close,
    .lightbox-nav {
        width: 40px;
        height: 40px;
    }
    .lightbox-prev { left: 10px; }
    .lightbox-next { right: 10px; }
    /* Detail-page sticky bar leaves room above the fold so the
       in-page bottom CTA isn't covered by the bar on first scroll. */
    body:has(.mobile-cta-bar-detail) main {
        padding-bottom: 80px;
    }
}

@media (max-width: 480px) {
    .detail-hero-grid {
        gap: 24px;
    }
    .detail-quickstats {
        grid-template-columns: repeat(2, 1fr);
    }
    /* On 2-col mobile, explicit col-2 placement would orphan the FT cell
       on its own row with col 1 empty. Reset to auto so it flows inline
       at the bottom of the panel instead. */
    .detail-quickstats .qs-lot-row {
        grid-column: auto;
    }
}

/* === Conditional Listings Link Routing + Modify Search CTA === */

/* Conditional Listings link visibility. Two anchors share the same slot in
   the navbar and footer; this media query toggles which one is visible.
   Desktop visitors hit Map Search (its inline filters work well there);
   mobile visitors hit a pre-filtered Results page in Karen's 4 highest-volume
   counties, because Map Search's mobile list view loses city filtering.
   No JS required — pure CSS so there is no flash before hydration. */
.listings-link-mobile { display: none; }
@media (max-width: 767px) {
    .listings-link-desktop { display: none; }
    .listings-link-mobile { display: inline-flex; }
}

/* Modify Search CTA — mobile only. Sits between the page-header band and
   the IDX injection point, giving Results-page visitors a persistent escape
   hatch to the Basic Search form (the mobile Results page has no inline
   filters of its own). Hidden on desktop where Map Search already exposes
   filter UI inline. */
.dr-modify-search-cta { display: none; }
@media (max-width: 767px) {
    .dr-modify-search-cta {
        display: block;
        background: var(--black);
        padding: 16px 0;
        border-top: 1px solid rgba(255, 215, 0, 0.2);
        border-bottom: 1px solid rgba(255, 215, 0, 0.2);
    }
    /* Layout (max-width, margin, side padding) is inherited from the base
       .container rule — only the modify-search-specific center alignment is
       added here so we do not duplicate width/margin/padding declarations. */
    .dr-modify-search-cta .container {
        text-align: center;
    }
    .dr-modify-search-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        padding: 12px 32px;
        background: var(--gold);
        color: var(--black);
        text-decoration: none;
        font-family: 'Inter', sans-serif;
        font-weight: 600;
        font-size: 1rem;
        border-radius: 4px;
        transition: background 0.3s ease;
        width: 100%;
        max-width: 320px;
    }
    .dr-modify-search-btn:hover,
    .dr-modify-search-btn:focus {
        background: var(--gold-dark);
    }

    /* Scope the CTA by IDX page category. IDX writes the category class onto
       the #IDX-main div it injects between idxStart/idxStop, so we use :has()
       on body to flip visibility per page type. Verified 2026-05-29 by
       fetching live IDX pages and inspecting #IDX-main's class list:
         /idx/search/mobile           → IDX-category-search
         /idx/details/listing/...     → IDX-category-details
         /idx/results/listings        → IDX-category-results  (CTA stays visible)
       :has() is supported on Safari 15.4+ and Chrome 105+, which covers the
       mobile browsers this CTA targets. */
    /* Hide on Search pages (the search form itself is on screen — CTA is redundant) */
    /* Hide on Detail pages (no refinement value when viewing a single listing) */
    /* Stays visible on Results pages where users need an escape hatch back to search */
    body:has(#IDX-main.IDX-category-search) .dr-modify-search-cta,
    body:has(#IDX-main.IDX-category-details) .dr-modify-search-cta {
        display: none !important;
    }

    /* Hide the sticky mobile CTA bar on the IDX Results (listings) page only.
       Reuses the same #IDX-main category-class hook documented above
       (Results → IDX-category-results, verified 2026-05-29). On the Results
       page the visitor is mid-scan of the listing grid, where the bottom bar
       overlaps results and its tap competes with browsing. Every other page
       — homepage, static listings, contact, and detail pages — keeps the
       bar (no IDX-category-results ancestor, so this rule doesn't match). */
    body:has(#IDX-main.IDX-category-results) .mobile-cta-bar {
        display: none !important;
    }
}

/* === Custom CCZ Search Component (Results page) ===========================
   Styling for the JS-built City/County/Zip autocomplete that replaces IDX's
   broken native location filter (see the component's own block in
   idx-wrapper-template.html for the full why/how and the URL contract).
   Visuals deliberately track the site's existing .form-input system — Inter,
   white field, gray border, gold focus ring, 6px radius — so the component
   reads as native Delta Realty chrome inside IDX's injected refinement panel.
   All colors come from :root tokens; no hard-coded hex here.
   ========================================================================== */
.dr-ccz-component {
    position: relative;
    margin-bottom: 12px;
    font-family: var(--font-body);
}

/* === Dropdown brand styling (shared by all 6 chips) =======================
   Brand body font across all dropdown CONTENT. The option items and the CCZ
   component already set var(--font-body) explicitly; this is the safety net so
   any IDX/browser-default text — chiefly the <legend> section headers, which had
   no Delta rule at all — inherits Inter too. Scoped to the dropdown menus + CCZ
   component so it can never leak into the page-level Playfair hero. (The chevron
   <i class="fa"> carets live in the toggle BUTTON, a sibling of .idx-dropdown__menu,
   so this never touches the FontAwesome glyph font.) */
#IDX-main .idx-dropdown__menu,
#IDX-main .dr-ccz-component {
    font-family: var(--font-body);
}

/* Unified section-header styling for ALL 6 chip dropdowns: the 5 native-style
   chips' <legend> labels (Property Type / Bedrooms / Bathrooms / Sort By /
   Price Range — previously IDX/browser-default) and the injected Location label
   (.dr-ccz-label). Small + semibold in --black so each header reads as a clear
   section title above the lighter, larger option rows (0.95rem, --gray-text). */
#IDX-main .idx-dropdown__menu legend,
#IDX-main .dr-ccz-label {
    margin: 0 0 8px;
    padding: 0;            /* neutralize the browser-default <legend> padding */
    font-family: var(--font-body);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--black);
}

/* Selected-item chips ----------------------------------------------------- */
.dr-ccz-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 4px; /* 4px gap between chips, per spec */
}
.dr-ccz-chips:not(:empty) {
    margin-bottom: 6px;
}
.dr-ccz-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 6px 4px 10px;
    background: var(--gray-light); /* light gray pill */
    color: var(--gray-text);       /* dark text */
    border-radius: var(--radius);  /* 6px */
    font-size: 0.85rem;
    line-height: 1.2;
}
.dr-ccz-chip-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--gray-muted);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    border-radius: 50%;
    transition: color var(--transition), background var(--transition);
}
.dr-ccz-chip-remove:hover,
.dr-ccz-chip-remove:focus {
    color: var(--black);
    background: rgba(0, 0, 0, 0.08);
    outline: none;
}

/* Text input — mirrors .form-input ---------------------------------------- */
.dr-ccz-input-wrap {
    position: relative; /* anchor for the absolutely-positioned dropdown */
}
.dr-ccz-input {
    width: 100%;
    padding: 14px 16px;
    font-family: var(--font-body);
    font-size: 14px !important; /* 16px avoids iOS zoom-on-focus, matches .form-input */
    color: var(--gray-text);
    background: var(--white);
    border: 1px solid var(--gray-light);
    border-radius: var(--radius);
    transition: border-color var(--transition), box-shadow var(--transition);
}
.dr-ccz-input::placeholder {
    color: var(--gray-muted);
    opacity: 0.6;
}
.dr-ccz-input:focus {
    outline: none;
    border-color: var(--gold);                     /* gold focus ring */
    box-shadow: 0 0 0 3px rgba(255, 215, 0, 0.15); /* matches .form-input:focus */
}

/* Autocomplete dropdown --------------------------------------------------- */
.dr-ccz-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 50;
    margin: 0;
    padding: 4px 0;
    list-style: none;
    max-height: 240px; /* scrolls past 240px, per spec */
    overflow-y: auto;
    background: var(--white);
    border: 1px solid var(--gray-light);
    border-radius: var(--radius);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); /* subtle shadow, per spec */
}
/* [hidden] alone would be overridden by the display rules above, so restore it
   explicitly — this is how the JS shows/hides the dropdown. */
.dr-ccz-dropdown[hidden] {
    display: none;
}
.dr-ccz-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px; /* 12px padding, per spec */
    cursor: pointer;
    transition: background var(--transition);
}
.dr-ccz-option:hover,
.dr-ccz-option.is-active { /* .is-active mirrors hover for keyboard nav */
    background: var(--gray-light);
}
.dr-ccz-option-name {
    color: var(--gray-text);
    font-size: 0.95rem;
}
.dr-ccz-option-type {
    flex-shrink: 0;
    color: var(--gray-muted);   /* muted gray */
    font-size: 0.7rem;
    text-transform: uppercase;  /* right-aligned uppercase type label */
    letter-spacing: 0.5px;
}

/* "Clear all" reset link ---------------------------------------------------- */
.dr-ccz-switch {
    display: inline-block;
    margin-top: 6px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--gold-dark); /* brand-gold cue, readable on white */
    font-family: var(--font-body);
    font-size: 0.8rem;
    text-decoration: underline;
    cursor: pointer;
}
.dr-ccz-switch[hidden] {
    display: none;
}
.dr-ccz-switch:hover,
.dr-ccz-switch:focus {
    color: var(--black);
    outline: none;
}

/* Mobile: full-width field, 44px tap targets, taller dropdown ------------- */
@media (max-width: 768px) {
    .dr-ccz-input {
        min-height: 44px; /* WCAG 2.5.5 target size */
        font-size: 16px !important; /* 16px stops iOS zoom-on-focus (desktop stays 14px) */
    }
    .dr-ccz-option {
        min-height: 44px;
        padding: 12px 14px;
    }
    .dr-ccz-chip {
        font-size: 0.9rem;
        padding: 6px 8px 6px 12px;
    }
    .dr-ccz-chip-remove {
        width: 24px;  /* larger tap target for chip removal */
        height: 24px;
        font-size: 1.25rem;
    }
    .dr-ccz-dropdown {
        max-height: 50vh; /* full-width below input, more room on tall phones */
    }
}

/* === Custom Property Type Filter chip =====================================
   Styling for the JS-built Property Type dropdown injected as the FIRST chip in
   IDX's refinement bar (see the component's own block in idx-wrapper-template.html
   for the full why/how, the empirical pt-code findings, and the templatable
   config contract). The chip reuses IDX's own button + menu classes, so it is
   visually identical to the native Price/Beds/Baths chips; only the option list
   inside the menu is custom and styled here. All colors come from :root tokens;
   no hard-coded hex.

   SCOPE: rules are scoped to #IDX-main (the IDX content root) rather than a
   specific form id, because the chip injects into EITHER IDX's native
   #IDX-refinementSearchForm (has-results) OR our synthesized #dr-refinementSearchForm
   (0-results) — both are descendants of #IDX-main, so one selector covers both.

   VISIBILITY OVERRIDE — why we don't reuse IDX-open:
   IDX reveals .idx-dropdown__menu on BOTH .IDX-open AND :focus-within. Because
   our chip button and every option button live inside .idx-dropdown, focus never
   leaves the component after a click, so a :focus-within-driven menu could never
   close on select. We therefore drive visibility with our own .dr-pt-open class.
   The id-led scope gives the hide rule specificity (0,1,2,0), which outranks IDX's
   :focus-within show rule (0,0,4,0) — one id beats any number of classes — and the
   open rule (0,1,3,0) outranks the hide rule, giving deterministic
   open / close / select-and-close behavior. The menu keeps every other IDX visual
   (border, padding, absolute positioning at >=1200px) since it still carries the
   .idx-dropdown__menu class.
   ========================================================================== */
#IDX-main .dr-pt-component .idx-dropdown__menu {
    display: none; /* outranks IDX's lower-specificity :focus-within show rule */
}
#IDX-main .dr-pt-component.dr-pt-open .idx-dropdown__menu {
    display: grid;      /* matches IDX's own open-state display */
    grid-row-gap: 1rem;
    outline: none;
}
/* Caret rotation is unified across all chips via the shared
   [aria-expanded="true"] .fa-angle-down rule (see "Chip chevron rotation"
   block near the end of this file). */

/* Option list inside the menu --------------------------------------------- */
#IDX-main .dr-pt-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
#IDX-main .dr-pt-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 10px 12px;
    border: none;
    background: transparent;
    border-radius: var(--radius); /* 6px */
    font-family: var(--font-body);
    font-size: 0.95rem;
    color: var(--gray-text);
    text-align: left;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
#IDX-main .dr-pt-option:hover,
#IDX-main .dr-pt-option:focus {
    background: var(--gray-light);
    outline: none;
}
#IDX-main .dr-pt-option.is-selected {
    color: var(--black);
    font-weight: 600;
}
/* Checkmark is present in the DOM for every option but only visible on the
   active selection — keeps row heights identical whether selected or not. */
#IDX-main .dr-pt-check {
    flex-shrink: 0;
    color: var(--gold-dark); /* readable gold cue on the white menu */
    font-size: 0.9rem;
    opacity: 0;
}
#IDX-main .dr-pt-option.is-selected .dr-pt-check {
    opacity: 1;
}

/* Mobile: 44px tap targets (WCAG 2.5.5 target size) ----------------------- */
@media (max-width: 768px) {
    #IDX-main .dr-pt-option {
        min-height: 44px;
        font-size: 1rem;
    }
}

/* === 0-results dual-state: empty message + synthesized refinement form =====
   On a 0-results page IDX drops its whole refinement panel, so the
   customRefinementBootstrap module injects an empty-state message and a
   synthesized #dr-refinementSearchForm (chip bar) into .idx-results. These rules
   style those injected pieces and make Modify Search a prominent escape hatch.
   All colors via :root tokens. Scoped so NONE of this touches has-results state
   (the synthesized form id + the :has(.--no-refinement) guard ensure that).
   ========================================================================== */

/* Empty-state message ----------------------------------------------------- */
#IDX-main .dr-empty-state {
    text-align: center;
    padding: 40px 20px 8px;
    margin: 0 auto;
    max-width: 640px;
}
#IDX-main .dr-empty-state__title {
    font-family: var(--font-heading);
    font-size: clamp(1.4rem, 3vw, 2rem);
    color: var(--black);
    margin: 0 0 10px;
}
#IDX-main .dr-empty-state__text {
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: 1.6;
    color: var(--gray-muted);
    margin: 0;
}

/* Hide the redundant "0 Listings" count row on 0-results. The empty-state
   heading ("No properties match your current filters") already communicates the
   zero count, so the gray count row below Apply Filters is duplicate noise.
   .idx-results__total wraps only the count <h4>, so hiding it removes the whole
   row. Scoped to 0-results via the :has(.--no-refinement) guard — has-results
   keeps its real count ("230 Listings"), which is useful. */
#IDX-main:has(.IDX-top-action__group--no-refinement) .idx-results__total {
    display: none;
}

/* Synthesized refinement form (chip bar) ---------------------------------- */
/* IDX's grid layout is scoped to .idx-results__refinement, which doesn't exist
   in 0-results state — so lay our synthesized bar out ourselves. */
#dr-refinementSearchForm {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: center;
    gap: 12px;
    padding: 8px 16px 20px;
    max-width: 900px;
    margin: 0 auto;
}
/* Each chip sits in its own auto-width column. The Location chip wrapper
   (.dr-loc-chip) is sized identically to Property Type so all 6 bar chips match;
   its .dr-ccz-component now lives inside the chip's dropdown panel, where the
   min-width keeps the panel comfortably wide for pills + input. */
#dr-refinementSearchForm .dr-pt-component,
#dr-refinementSearchForm .dr-loc-chip {
    flex: 0 0 auto;
    min-width: 200px;
}
#dr-refinementSearchForm .dr-ccz-component {
    flex: 1 1 280px;
    min-width: 240px;
    margin-bottom: 0; /* override the component's default bottom margin in this row */
}
/* Collapsible Location chip (0-results only) — same visibility override as the
   other 5 synthesized chips (.dr-pt-component et al): our .dr-loc-open class drives
   the menu, outranking IDX's :focus-within reveal (the CCZ input lives inside the
   menu, so focus never leaves the chip and a :focus-within-driven menu could never
   close on interaction). Caret rotation rides the shared [aria-expanded] rule.
   .dr-loc-chip exists only in the synthesized #dr-refinementSearchForm, so
   has-results is untouched. */
#IDX-main .dr-loc-chip .idx-dropdown__menu {
    display: none;
}
#IDX-main .dr-loc-chip.dr-loc-open .idx-dropdown__menu {
    display: block;
}
/* The stub native CCZ group is anchor-only — never shown. */
#dr-refinementSearchForm .dr-synth-ccz-group {
    display: none;
}
/* Apply Filters button — inherits IDX's .IDX-btn styling; just align it in-row. */
#dr-refinementSearchForm .dr-synth-apply {
    flex: 0 0 auto;
    align-self: stretch;
    min-height: 44px;
    cursor: pointer;
}

/* Hide the IDX-native action buttons on 0-results — New Search, Modify Search,
   and Save Search. On 0-results the 6 custom chips provide all filter
   modification inline, so these float disconnected at the top-right and are
   redundant; the "Listings" nav link is the start-over path. Scoped to 0-results
   via the :has(.--no-refinement) guard so has-results keeps all three (its
   #IDX-saveSearch lives inside #IDX-refinementSearchForm, a different container).
   NOTE: on mobile IDX already hides these three (they carry IDX-hide-filters--
   desktop) and consolidates actions into #idx-results-mobile-control — so this is
   effectively the desktop-state cleanup. Replaces the earlier "prominent Modify
   Search" treatment, which is moot now that Modify Search is hidden here. */
#IDX-main:has(.IDX-top-action__group--no-refinement) .IDX-newSearch,
#IDX-main:has(.IDX-top-action__group--no-refinement) .IDX-modifySearch,
#IDX-main:has(.IDX-top-action__group--no-refinement) #IDX-saveSearch {
    display: none;
}

@media (max-width: 768px) {
    #dr-refinementSearchForm {
        flex-direction: column;
        align-items: stretch;
        /* Lock the bar to the full available width. Without an explicit width the
           form is a shrink-to-fit block, so its width tracked the widest child's
           max-content — which GROWS with the number of CCZ pills (measured: 0–1
           pills -> 240px fields, 3 pills -> 342px fields). width:100% pins every
           field at the wide/expanded state regardless of pill count. Scoped to
           mobile + the 0-results synthesized form (#dr-refinementSearchForm only
           exists in 0-results), so has-results and desktop are untouched. */
        width: 100%;
    }
    #dr-refinementSearchForm .dr-pt-component,
    #dr-refinementSearchForm .dr-ccz-component,
    #dr-refinementSearchForm .dr-loc-chip {
        min-width: 0;
    }
}

/* Mobile 0-results — collapse the Location block's dead height ----------------
   Bar order (Location | PT | Price | Beds | Baths | Sort | Apply) is now DOM-
   driven by the synthesis module's orderSynthBar pass (idx-wrapper-template.html),
   identical on both viewports — so NO flex `order` overrides live here anymore.

   This rule remains purely to size the Location block correctly on mobile.
   .dr-ccz-component carries `flex: 1 1 280px` for the desktop row; in the mobile
   flex-direction:column layout that 280px flex-basis lands on the MAIN (vertical)
   axis, inflating the block to 280px tall when its content is only ~126px. Since
   Location now sits at the TOP of the stack, that ~154px of dead space would push
   every chip below it down. `flex: 0 0 auto` sizes the block to its content.

   Scoped to mobile + #dr-refinementSearchForm (0-results only). Has-results CCZ
   lives in the Location dropdown inside #IDX-refinementSearchForm — a different id
   this selector cannot match — so has-results is untouched at any viewport. */
@media (max-width: 768px) {
    #dr-refinementSearchForm .dr-ccz-component {
        flex: 0 0 auto;
    }
}

/* === Custom Sort By chip (Phase 2.1) =======================================
   Mirrors the Property Type chip's dropdown visuals (see that block for the full
   why/how of the .dr-*-open visibility override vs IDX's :focus-within). Scoped to
   #IDX-main so it covers both the native and synthesized refinement forms. All
   colors via :root tokens. Layout/position is provisional — Prompt 4 (bar
   restructure) owns final placement.
   ========================================================================== */
#IDX-main .dr-sort-component .idx-dropdown__menu {
    display: none; /* outranks IDX's lower-specificity :focus-within show rule */
}
#IDX-main .dr-sort-component.dr-sort-open .idx-dropdown__menu {
    display: grid;
    grid-row-gap: 1rem;
    outline: none;
}
/* Caret rotation: shared [aria-expanded="true"] .fa-angle-down rule (end of file). */

#IDX-main .dr-sort-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
#IDX-main .dr-sort-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 10px 12px;
    border: none;
    background: transparent;
    border-radius: var(--radius);
    font-family: var(--font-body);
    font-size: 0.95rem;
    color: var(--gray-text);
    text-align: left;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
#IDX-main .dr-sort-option:hover,
#IDX-main .dr-sort-option:focus {
    background: var(--gray-light);
    outline: none;
}
#IDX-main .dr-sort-option.is-selected {
    color: var(--black);
    font-weight: 600;
}
#IDX-main .dr-sort-check {
    flex-shrink: 0;
    color: var(--gold-dark);
    font-size: 0.9rem;
    opacity: 0;
}
#IDX-main .dr-sort-option.is-selected .dr-sort-check {
    opacity: 1;
}

/* Provisional in-bar sizing for the synthesized (0-results) form, matching the
   other chips there. Has-results layout comes from IDX's own grid. */
#dr-refinementSearchForm .dr-sort-component {
    flex: 0 0 auto;
    min-width: 200px;
}

@media (max-width: 768px) {
    #IDX-main .dr-sort-option {
        min-height: 44px;
        font-size: 1rem;
    }
    #dr-refinementSearchForm .dr-sort-component {
        min-width: 0;
    }
}

/* === Custom Beds + Baths chips (Phase 2.2) ==================================
   Shared visuals for BOTH the Beds (.dr-beds-component) and Baths
   (.dr-baths-component) chips — they're built by one createMinChip() factory, so
   one .dr-minchip-* ruleset styles both. Mirrors the Sort/PT chip dropdown (see
   the PT block for the .dr-*-open vs IDX :focus-within rationale). Scoped to
   #IDX-main so it covers the native AND synthesized refinement forms. All colors
   via :root tokens. Position is provisional — Prompt 4 (bar restructure) owns it.
   ========================================================================== */
#IDX-main .dr-minchip-component .idx-dropdown__menu {
    display: none; /* outranks IDX's lower-specificity :focus-within show rule */
}
#IDX-main .dr-minchip-component.dr-minchip-open .idx-dropdown__menu {
    display: grid;
    grid-row-gap: 1rem;
    outline: none;
}
/* Caret rotation: shared [aria-expanded="true"] .fa-angle-down rule (end of file). */

#IDX-main .dr-minchip-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
#IDX-main .dr-minchip-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 10px 12px;
    border: none;
    background: transparent;
    border-radius: var(--radius);
    font-family: var(--font-body);
    font-size: 0.95rem;
    color: var(--gray-text);
    text-align: left;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
#IDX-main .dr-minchip-option:hover,
#IDX-main .dr-minchip-option:focus {
    background: var(--gray-light);
    outline: none;
}
#IDX-main .dr-minchip-option.is-selected {
    color: var(--black);
    font-weight: 600;
}
#IDX-main .dr-minchip-check {
    flex-shrink: 0;
    color: var(--gold-dark);
    font-size: 0.9rem;
    opacity: 0;
}
#IDX-main .dr-minchip-option.is-selected .dr-minchip-check {
    opacity: 1;
}

/* Provisional in-bar sizing for the synthesized (0-results) form, matching the
   other chips there. Has-results layout comes from IDX's own grid. */
#dr-refinementSearchForm .dr-minchip-component {
    flex: 0 0 auto;
    min-width: 150px;
}

@media (max-width: 768px) {
    #IDX-main .dr-minchip-option {
        min-height: 44px;
        font-size: 1rem;
    }
    #dr-refinementSearchForm .dr-minchip-component {
        min-width: 0;
    }
}

/* === Custom Price range chip (Phase 2.3) ===================================
   One bar chip whose dropdown holds a Min + Max <select> pair (the range
   pattern). Reuses the shared chip shell/visibility model (see the PT block for
   the .dr-*-open vs IDX :focus-within rationale). Scoped to #IDX-main so it
   covers the native AND synthesized refinement forms. All colors via :root
   tokens. Position is provisional — Prompt 4 (bar restructure) owns it.
   ========================================================================== */
#IDX-main .dr-price-component .idx-dropdown__menu {
    display: none; /* outranks IDX's lower-specificity :focus-within show rule */
}
#IDX-main .dr-price-component.dr-price-open .idx-dropdown__menu {
    display: block;
    outline: none;
}
/* Caret rotation: shared [aria-expanded="true"] .fa-angle-down rule (end of file). */

#IDX-main .dr-price-row {
    display: flex;
    align-items: flex-end;
    gap: 12px;
}
#IDX-main .dr-price-col {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 120px;
}
#IDX-main .dr-price-sublabel {
    font-family: var(--font-body);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--gray-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
#IDX-main .dr-price-select {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--gray-light);
    border-radius: var(--radius);
    background: #fff;
    font-family: var(--font-body);
    font-size: 0.95rem;
    color: var(--gray-text);
    cursor: pointer;
}
#IDX-main .dr-price-select:focus {
    outline: none;
    border-color: var(--gold-dark);
}
#IDX-main .dr-price-note {
    margin: 10px 0 0;
    font-family: var(--font-body);
    font-size: 0.82rem;
    color: var(--gold-dark);
}

/* Provisional in-bar sizing for the synthesized (0-results) form, matching the
   other chips there. Has-results layout comes from IDX's own grid. */
#dr-refinementSearchForm .dr-price-component {
    flex: 0 0 auto;
    min-width: 200px;
}

@media (max-width: 768px) {
    #IDX-main .dr-price-select {
        min-height: 44px;
        font-size: 1rem;
    }
    #dr-refinementSearchForm .dr-price-component {
        min-width: 0;
    }
}

/* === Brand-gold "filter applied" chip cue ==================================
   Each chip module sets data-applied="true" on its chip button (for Location, the
   "More Filters"/#idx-refinement-more button on has-results and the
   #dr-refinement-location button on 0-results) whenever its current state
   diverges from the Delta default-landing baseline (PT explicitly user-picked, Beds/Baths≠Any,
   Price has a min/max, Sort explicitly user-picked, Location a non-empty set ≠ the 3 baseline counties). On the
   default landing NO chip is applied, so none show gold.

   Treatment: a 4px gold (#FFD700) left-border accent + a bolder (600) label.
   The label TEXT is deliberately left at its default dark colour (#333, ~12:1) —
   NOT recoloured: measured gold-dark (#b0912f) on the chips' light background is
   only 3.03:1, which fails WCAG AA for 14px text (needs 4.5:1; 3:1 covers large
   text only). The "applied" state is conveyed by three non-colour-dependent cues —
   the gold border, the heavier weight, and the label's own text change
   ("Beds"→"3+", "Property Type"→"Commercial") — so it satisfies WCAG 1.4.1 (Use of
   Colour) and never leans on a low-contrast colour. #FFD700 is decorative (border
   only → no text-contrast requirement). Location now rides the same button cue in
   both states (the chip button carries the border + bolded "Location (N)" label),
   so its panel — the .dr-ccz-component inside the dropdown — gets no accent (see
   the suppression rule below). Scoped to #IDX-main so it covers both the native
   (has-results) and synthesized (0-results) bars, all viewports. Colours via
   :root tokens.

   !important: the IDX chip buttons (.IDX-btn-primary …) set their own border and
   font-weight at a specificity a clean attribute selector can't reach, so the
   brand overrides are forced. Scoped to data-applied="true" (set only by our chip
   modules), so nothing else is affected. */
#IDX-main [data-applied="true"] {
    border-left: 4px solid var(--gold) !important;
}
/* ...EXCEPT the Location .dr-ccz-component when it sits INSIDE a dropdown menu —
   which, since Polish #3, is BOTH states (has-results: IDX's More Filters menu;
   0-results: the .dr-loc-chip menu wrapping the component). markCczApplied() flags
   the active chip button (#idx-refinement-more / #dr-refinement-location) AND the
   .dr-ccz-component; the button keeps the gold accent above, but on the in-menu
   component that same border-left rendered as a stray vertical gold bar down the
   dropdown panel's interior — which the other 5 chips' panels don't have. This one
   rule suppresses it in both states, so the gold cue rides the chip button alone.
   Higher specificity than the rule above, so it wins despite both carrying
   !important. */
#IDX-main .idx-dropdown__menu .dr-ccz-component[data-applied="true"] {
    border-left: none !important;
}
#IDX-main [data-applied="true"]:not(.dr-ccz-component),
#IDX-main [data-applied="true"]:not(.dr-ccz-component) > span {
    font-weight: 600 !important;
}

/* === Chip chevron rotation (unified) ======================================
   An aria-expanded true/false pair drives the caret flip for EVERY refinement
   chip, replacing the four per-chip rules that each keyed off a different open-class
   (.dr-pt-open / .dr-sort-open / .dr-price-open / .dr-minchip-open). All six
   chip toggles already set aria-expanded for accessibility — our five custom
   chips flip it in their open()/close() (in lockstep with the open-class that
   still drives menu VISIBILITY), and IDX's native "More Filters" button (the
   renamed Location chip) sets it too. So aria-expanded is the one signal common
   to all of them, and keying rotation off it gives uniform behavior regardless
   of how the chip opened/closed (button click, outside click, programmatic).

   The caret element is <i class="fa fa-angle-down">; .fa-angle-down is the
   stable hook. Down (default) when closed, 180° (up) when open — an INSTANT
   swap (no transition), matching the Location chip's snap so all 6 are uniform.

   Scoped to #IDX-main so it only touches the refinement bar. The combobox
   input inside the CCZ component also carries aria-expanded but has NO
   .fa-angle-down child, so it's unaffected. Location's chevron rides this rule
   for free IF IDX sets aria-expanded on #idx-refinement-more (standard
   dropdown a11y) — additive, no JS override of IDX's native button.

   NO transition on the caret: the rotation snaps INSTANTLY (per Wes's UX call),
   matching the Location chip. A prior 0.15s transform transition animated the 5
   custom chips but NOT Location (IDX's native button never carried it), so
   dropping it makes all 6 uniform. Menu open/close is display-toggled, not
   animated, so nothing else is affected. */
#IDX-main [aria-expanded="true"] .fa-angle-down {
    transform: rotate(180deg);
}
/* ...and force the caret back DOWN when closed, overriding IDX's OWN focus-based
   caret rotation. IDX's (cross-origin) stylesheet rotates the caret while the
   .idx-dropdown has focus (a :focus-within / button :focus rule). After a re-click
   CLOSE the button keeps focus, so aria-expanded correctly flips to "false" and the
   menu hides — but IDX's focus rule kept the caret rotated UP; it only snapped down
   once focus left (outside-click or clicking another chip). Binding rotation strictly
   to aria-expanded here makes "closed" always read as down, regardless of focus.
   id-scoped + !important so it wins even if IDX's focus rule is itself !important. */
#IDX-main [aria-expanded="false"] .fa-angle-down {
    transform: none !important;
}

/* === Location button override (defensive) =================================
   Takes over IDX's native #idx-refinement-more (the renamed "Location" button) to
   add toggle-close. See the customCCZ "Location button toggle override" block in
   idx-wrapper-template.html for the full rationale. IDX reveals the dropdown via a
   :focus-within rule, so re-clicking the button never loses focus and never closes
   (Bug 3). The override JS toggles a .dr-location-open class on the button (which it
   first marks .dr-location-managed); these rules gate the SIBLING .idx-dropdown__menu
   on that class with !important, outranking IDX's lower-specificity :focus-within
   reveal.

   Assumed IDX DOM: button #idx-refinement-more and its sibling .idx-dropdown__menu
   share a .idx-dropdown parent; the chevron is i.fa.fa-angle-down inside the button.
   If this block stops having effect, confirm those still hold and that IDX hasn't
   added a higher-specificity or !important reveal rule of its own. Only the
   IDX-native Location button carries .dr-location-managed, so these rules can't
   touch our 5 custom chips. */
.dr-location-managed:not(.dr-location-open) + .idx-dropdown__menu,
.dr-location-managed:not(.dr-location-open) ~ .idx-dropdown__menu {
    display: none !important;
}
.dr-location-managed.dr-location-open + .idx-dropdown__menu,
.dr-location-managed.dr-location-open ~ .idx-dropdown__menu {
    display: block !important;
}
/* Chevron rotation via our state class — complements the shared
   [aria-expanded="true"] .fa-angle-down rule above. Either signal rotates the
   caret, so Location's chevron stays correct even if IDX overwrites aria-expanded
   on its own button. */
.dr-location-managed.dr-location-open .fa-angle-down {
    transform: rotate(180deg);
}

/* ============================================================================
   Lead-capture cleanup
   ----------------------------------------------------------------------------
   Delta does NOT use IDX's lead-capture pipeline — leads come through Karen's own
   forms (Schedule Consultation, Sell Your Place, Talk to Us). IDX's hearts / Save
   Search / signup flow funnel users into a parallel IDX-controlled lead silo Karen
   doesn't monitor, so we hide those entry points. CSS-only display:none — no change
   to IDX's lead JS, forms, URLs, or admin. Built as separate commits so each piece
   reverts independently.
   ============================================================================ */

/* Hearts on listing cards (and the detail page) — IDX's "save property" control
   opens its Sign Up modal. Scoped to #IDX-main so the static pages.dev listing
   pages (a different DOM/origin) are untouched.
   NOTE: IDX's result markup is runtime-injected cross-origin (NOT in the repo), so
   these are IDX-Broker-convention class names + two case-specific [class*=…]
   substring hedges, not a live-verified selector. display:none can only hide, so a
   wrong guess is a no-op, never a break. VERIFY on the live results/detail page; if
   a heart persists, add its exact class to this list (one-line change). */
#IDX-main .IDX-resultsCellSave,
#IDX-main .IDX-saveLink,
#IDX-main .IDX-savedLink,
#IDX-main .IDX-controlSaveProperty,
#IDX-main .IDX-detailsSaveProperty,
#IDX-main [class*="SaveProperty"],
#IDX-main [class*="saveProperty"] {
    display: none !important;
}

/* IDX leadToolsBar — the "Welcome, <name> (?)" account bar IDX renders for a
   logged-in IDX user. In the wrapper it shows broken-looking text (empty paren)
   and Karen doesn't manage IDX user accounts, so it's noise. Targeted by its
   IDX-Broker id #IDX-leadToolsBar (NOT scoped to #IDX-main: the bar can render
   above/outside that container). display:none reclaims its vertical space cleanly.
   Verify live that the Welcome string is gone and nothing downstream shifts. */
#IDX-leadToolsBar {
    display: none !important;
}

/* SAVE SEARCH — extend the hide to HAS-results. It was already hidden on 0-results
   by the .IDX-newSearch/.IDX-modifySearch/#IDX-saveSearch :has(.--no-refinement)
   rule above (those two siblings stay hidden only on 0-results). #IDX-saveSearch is
   confirmed (idx-results-bar-structure): on has-results it lives inside
   #IDX-refinementSearchForm. This rule hides it in BOTH states — same lead-silo
   rationale (signup modal → IDX alerts branded as Karen). APPLY FILTERS / NEW
   SEARCH / MODIFY SEARCH stay visible on has-results; the Listings nav is the
   start-over path. */
#IDX-main #IDX-saveSearch {
    display: none !important;
}

/* ============================================================================
   Mobile filter polish
   ----------------------------------------------------------------------------
   Cleanups for IDX's mobile results bottom action bar (#idx-results-mobile-control:
   Filter / Save / New Search / Modify / Hide Map) and the chip dropdowns. ALL rules
   here are scoped to the ≤768px breakpoint so desktop is never touched. Selectors
   verified against the live /idx/results markup (curl, 2026-06-06). Each rule below
   shipped as its own commit so it reverts independently.
   ============================================================================ */

/* Hide NEW SEARCH in the mobile bottom banner — redundant alongside Filter; the
   Listings nav is the start-over path. IDX changed New Search's href from
   /idx/search/basic to a search-state-encoded /idx/search/resultslistings… URL,
   so the old $= "ends in /idx/search/basic" match broke and NEW SEARCH reappeared.
   Match any #idx-results-mobile-control /idx/search/ link EXCEPT Modify (carries
   ?modifySearch); Save=#saveSearch and Filter/Hide Map have no href, so they're
   unaffected. */
@media (max-width: 768px) {
    #idx-results-mobile-control a[href*="/idx/search/"]:not([href*="modifySearch"]) {
        display: none !important;
    }
}

/* Hide the bottom FILTER button while the drawer is open, so APPLY FILTERS (inside
   the drawer) is the only visible action — no two-button confusion. Uses IDX's OWN
   open-state hooks (verified in the live markup): the toggle #idx-mobile-filters
   carries aria-expanded (flips to "true" when the drawer opens), and IDX adds
   .idx-results--refinement-open to the results container. Either signal hides the
   button; both revert on close, so it reappears — no JS or state of our own needed. */
@media (max-width: 768px) {
    #idx-mobile-filters[aria-expanded="true"],
    .idx-results--refinement-open #idx-mobile-filters {
        display: none !important;
    }
}

/* Premium-banner restyle of the mobile FILTER toggle — replaces IDX's loud solid
   button with Delta's hero/header identity: semi-transparent near-black fill, gold
   border, off-white bold uppercase text. !important to outrank IDX's .IDX-btn-link
   styling. 48px tap target (> WCAG 2.5.5 44px); off-white (#F5F5F5) on the dark fill
   ≈ 15:1 (well past WCAG AA). Touch/hover deepens the fill and shifts text to gold. */
@media (max-width: 768px) {
    #idx-mobile-filters {
        background: rgba(26, 26, 26, 0.85) !important; /* var(--black) #1A1A1A @ 85% */
        border: 2px solid var(--gold) !important;
        color: var(--gray-bg) !important;              /* #F5F5F5 off-white */
        font-weight: 700 !important;
        letter-spacing: 0.06em !important;
        text-transform: uppercase !important;
        min-height: 48px !important;
        padding: 12px 20px !important;
        border-radius: var(--radius) !important;
        box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.15) !important;
        transition: background var(--transition), color var(--transition) !important;
    }
    #idx-mobile-filters:hover,
    #idx-mobile-filters:focus,
    #idx-mobile-filters:active {
        background: var(--black) !important;
        color: var(--gold) !important;
        outline: none !important;
    }
}

/* Keep an open chip dropdown ABOVE the fixed header so its section label
   ("Location", "Bedrooms", …) isn't painted over by the sticky chrome.
   DIAGNOSIS: the header is fixed — trust bar z-index 1001, navbar z-index 1000 —
   while the chip menus are IDX-positioned (position:absolute) with NO z-index of
   our own, so an open menu that overlaps the header region stacks BENEATH it and
   its top gets clipped. Raising the menu's z-index above the header (Option B —
   stacking fix) keeps the whole dropdown visible whether it opens up or down.
   Closed menus are display:none, so this only affects the one open menu. Mobile
   only; desktop chip behavior unchanged.
   NOTE: I could not observe the live mobile render (cross-origin, runtime-injected),
   so this assumes the clipping is a STACKING overlap (consistent with "the header
   overlaps the dropdown"). If a live check shows it's instead OVERFLOW clipping by a
   scroll container, the fix would be scroll-margin-top / an overflow tweak rather
   than z-index — verify on a 375px viewport. */
@media (max-width: 768px) {
    #IDX-main .idx-dropdown__menu {
        z-index: 1002;
    }
    /* CCZ autocomplete list (default z-index 50) sits above its own Location menu. */
    #IDX-main .dr-ccz-dropdown {
        z-index: 1003;
    }
}
