/* =================================================================
   Tony Gutierrez — Ocala New Homes  ·  LUXURY PREVIEW THEME
   -----------------------------------------------------------------
   Quiet-luxury treatment: midnight + warm ivory, champagne gold used
   sparingly, elegant serif display over a clean geometric sans, and
   generous whitespace. Preview only — does not touch styles.css.
   ================================================================= */
:root{
  /* --- channel tokens -------------------------------------------------
     Every translucent brand colour is expressed as rgba(var(--x-rgb), α) so a
     hue lives in exactly ONE place. Chosen over color-mix() deliberately: this
     works everywhere, needs no fallback, and the census found 62 longhand
     rgba() values that collapse into these five with no visual change. */
  --midnight-rgb:   18,24,32;
  /* --- overlay scrim -----------------------------------------------------
     NOT the same value as --midnight, and that is deliberate. Hero scrims run
     DARKER than panel surfaces because they are the only thing holding hero
     text above AA over a bright Florida sky. Collapsing them into --midnight
     (a 4% lightening) pushed /floor-plans at 375px from 3.03 to 2.88 against a
     3.0 threshold — measured, not guessed. Contrast beats consolidation, so
     this is a legitimate second dark token, not a duplicate.
     One value for every scrim, which also makes hero darkening uniform. */
  --midnight-deep-rgb: 10,14,20;
  --midnight-2-rgb: 28,40,54;
  --ivory-rgb:      247,243,236;
  --gold-rgb:       182,151,95;
  --gold-soft-rgb:  203,180,137;
  --black-rgb:      0,0,0;
  --white-rgb:      255,255,255;
  --redtag-rgb:     138,47,56;
  --success-rgb:    53,208,127;
  /* Three greens were in use with three different meanings. --success is the
     live/online dot; --verified is the deeper green shared by the Move-In Ready
     badge and the pin-check centroid chip (those two were 3f7d54 and 3c7846 —
     a 22/765 difference nobody could see, so they are now one token). */
  --verified:       #3f7d54;
  --verified-rgb:   63,125,84;
  /* Not brand colours — named so they cannot be "cleaned up" into the palette.
     --map-surface is what shows THROUGH/behind Leaflet tiles while they load;
     warming it to ivory would make every map flash the wrong colour. */
  --map-surface:    #eef1f4;
  --midnight-3:     #243244;   /* third dark lift, hero placeholder gradients */
  --placeholder:    #b3ada0;   /* form placeholder text — lighter than --muted */
  /* Text-weight variants: the badge greens/ambers above are for fills and
     icons; these are the darker AA-contrast versions used as TEXT on a light
     chip (the shortlist match-quality labels). Same hue family, different job. */
  --verified-ink:     #1d6b45;
  --verified-ink-rgb: 29,107,69;
  --warning-ink:      #8a6a1f;
  --video-bg:         #000;    /* letterbox behind <video>, not a brand black */
  --redtag:    #8a2f38;   /* deep garnet — was a stray second :root block */
  --gold-deep: #8f7440;   /* was used only as a var() fallback, never defined */
  --success:   #35d07f;
  --warning:   #c98f2f;
  --midnight:  #121820;   /* deep charcoal-navy — headings, footer, primary */
  --midnight-2:#1c2836;   /* lifted panel / hover                           */
  --ink:       #2b2f35;   /* body text on ivory                             */
  --muted:     #8a8578;
  /* --muted is 3.68:1 on white — fine for decorative text, BELOW WCAG AA for
     anything you have to read. Small copy that carries information (prices,
     counts, specs) uses --muted-aa: 5.47:1 on white, 4.53:1 on cream. */
  --muted-aa:  #6e695c;   /* warm secondary text                            */
  --ivory:     #f7f3ec;   /* warm page background (not stark white)         */
  --cream:     #efe9df;   /* deeper tint for alternating sections           */
  --gold:      #b6975f;   /* muted champagne — thin lines & small accents   */
  --gold-soft: #cbb489;   /* lighter champagne for on-dark hairlines        */
  --line:      #e4ded1;   /* hairline borders on light                      */
  --white:     #ffffff;
  --wa:        #7fae8e;   /* muted, de-saturated whatsapp green             */
  --radius:    2px;       /* barely-there softness                          */
  --shadow:    0 18px 50px -24px rgba(var(--midnight-rgb),.28);
  --shadow-lift:0 30px 70px -30px rgba(var(--midnight-rgb),.40);
  --max: 1200px;
  --callbar-h: 56px;      /* height of the sticky mobile Call/Text bar        */
  --radius-pill: 99px;    /* only things that are genuinely pills             */

  /* ---- motion scale. Every transition picks one of these three; a one-off
     duration is a bug, not a decision. ------------------------------------ */
  --ease:     cubic-bezier(.22,.61,.36,1);   /* the house curve               */
  --ease-in:  cubic-bezier(.55,.06,.68,.19);
  --dur-1: 180ms;   /* micro — hover, focus, pressed                          */
  --dur-2: 240ms;   /* standard — modal, menu, lightbox, page fade            */
  --dur-3: 420ms;   /* deliberate — scroll reveals, nav background            */

  /* ---- elevation scale -------------------------------------------------- */
  --shadow-sm:   0 6px 18px -10px rgba(var(--midnight-rgb),.22);
  --shadow-modal:0 48px 110px -40px rgba(var(--midnight-rgb),.62);

  /* ---- THE LAYER SCALE --------------------------------------------------
     Every z-index in this stylesheet comes from here. A raw number anywhere
     else is a bug: three separate times a modal shipped underneath the sticky
     header, and each time it was "fixed" by inventing a bigger number, which
     is what produced 900 / 1200 / 1300 competing with 100 / 140 / 170.

     The order below IS the product decision, written once:
       a modal outranks the header. Always. On every page.

     The header deliberately sits LOW (100). It is page chrome, not a layer
     that competes with overlays — the old 900 is exactly what buried the
     Schedule modal's close button under .nav__inner. */
  --z-base:            0;    /* normal page content                          */
  --z-sticky-header: 100;    /* .nav — sticky chrome, below every overlay     */
  --z-dropdown:      200;    /* menus/panels anchored to a trigger            */
  --z-chat-launcher: 300;    /* floats over the page, never over a modal      */
  --z-overlay-scrim: 900;    /* the dimming layer beneath a modal             */
  --z-modal:        1000;    /* dialogs, lightboxes, the wizard, the menu     */
  --z-toast:        1100;    /* transient messages — the only thing above     */

  /* Sticky bars that live UNDER the header (filter rails, partner subnav).
     Derived, so they can never drift past the header they hang from. */
  --z-sticky-sub: calc(var(--z-sticky-header) - 1);

  /* ---- LOCAL layer scale ------------------------------------------------
     A separate, deliberately tiny family for ordering siblings INSIDE one
     component's own stacking context (a caption over its photo, a badge over
     a card image). These never interact with the global scale — putting a
     card badge on --z-modal would be meaningless — so they are named apart
     rather than folded in. Two families, zero raw numbers. */
  --z-local-behind: -2;      /* background media under a scrim                */
  --z-local-under:  -1;      /* decorative wash behind content                */
  --z-local-base:    0;
  --z-local-raise:   1;      /* content above its own decoration              */
  --z-local-over:    2;      /* overlay strip within a component              */
  --z-local-control: 3;      /* the component's own controls, topmost         */

  /* --- spacing scale ---------------------------------------------------
     THE SCALE DID NOT EXIST BEFORE 2026-08-02. Vertical rhythm was a field
     of one-off rem literals — a census of .hd__* alone found .3/.35/.4/.5/
     .7/.9/1.6/2.5rem, none of which agreed with any other block. That is
     survivable while every fragment is its own island; it stops being
     survivable the moment fragments are consolidated INTO sections, because
     then the gaps sit next to each other and every disagreement is visible.

     Ratio is ~1.5 with a 4px base, so every step lands on a whole pixel at
     the root font size and two adjacent steps are always distinguishable.
     Use the token, not the literal — a value that needs to be between two
     steps is nearly always a sign the wrong step was chosen. */
  --sp-1:  .25rem;   /*  4px — icon-to-label, chip innards            */
  --sp-2:  .5rem;    /*  8px — inside a control                       */
  --sp-3:  .75rem;   /* 12px — between controls in a row              */
  --sp-4:  1rem;     /* 16px — label to value, tight stack            */
  --sp-5:  1.5rem;   /* 24px — between blocks inside one component    */
  --sp-6:  2rem;     /* 32px — component to component                 */
  --sp-7:  3rem;     /* 48px — sub-section separation                 */
  --sp-8:  4rem;     /* 64px — section head to section body           */
  --sp-9:  6rem;     /* 96px — section to section (.section padding)  */
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;overflow-x:clip}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  font-family:'Jost',system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
  color:var(--ink);
  background:var(--ivory);
  line-height:1.7;
  font-weight:300;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:clip; /* contain the off-canvas mobile menu so nothing overflows sideways */
}
img{display:block;width:100%;height:100%;object-fit:cover}
a{color:inherit;text-decoration:none}
h1,h2,h3,h4{font-family:'Cormorant Garamond',Georgia,serif;line-height:1.12;color:var(--midnight);font-weight:500}

/* Small letter-spaced uppercase label — the luxury-hotel eyebrow */
.eyebrow,.section__eyebrow,.hero__eyebrow{
  font-family:'Jost',sans-serif;text-transform:uppercase;
  letter-spacing:.34em;font-size:0.75rem;font-weight:500;color:var(--gold);
}

/* ---------- Buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:0.5rem;
  font-family:'Jost',sans-serif;font-weight:500;text-transform:uppercase;
  letter-spacing:.2em;font-size:0.75rem;
  padding:1rem 2rem;border-radius:var(--radius);border:1px solid transparent;
  cursor:pointer;white-space:nowrap;
  transition:background var(--dur-2) var(--ease),color var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease),transform var(--dur-2) var(--ease);
}
.btn svg{width:15px;height:15px;flex:0 0 auto}
/* Soft-solid midnight (primary on light) */
.btn--solid{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}
.btn--solid:hover{background:var(--midnight-2);border-color:var(--midnight-2)}
/* Soft-solid ivory (primary on dark hero) */
.btn--ivory{background:var(--ivory);color:var(--midnight);border-color:var(--ivory)}
.btn--ivory:hover{background:var(--gold);border-color:var(--gold);color:var(--midnight)}
/* Hairline outline on light */
.btn--line{background:transparent;color:var(--midnight);border-color:var(--midnight)}
.btn--line:hover{background:var(--midnight);color:var(--ivory)}
/* Gold hairline / ghost — for on-dark surfaces */
.btn--ghost{background:transparent;color:var(--ivory);border-color:rgba(var(--gold-soft-rgb),.5)}
.btn--ghost:hover{border-color:var(--gold-soft);background:rgba(var(--gold-soft-rgb),.08)}
/* Full-width buttons are block-level and carry sentence-length labels, so the
   base .btn `white-space:nowrap` must NOT apply here. It did, and the estimator's
   "Want real numbers..." CTA gave .est__output a 568px min-content — which forced
   the .est grid track to 568px inside a 327px column on every phone. The page
   never scrolled sideways (html/body are overflow-x:clip) so the right side was
   simply cut off. Wrapping is correct for every .btn--full usage. */
.btn--full{width:100%;white-space:normal;text-align:center;line-height:1.35}

/* Refined text link ("View Homes →") */
.link-more{
  display:inline-block;font-family:'Jost',sans-serif;text-transform:uppercase;
  letter-spacing:.2em;font-size:0.75rem;font-weight:500;color:var(--midnight);
  padding-bottom:3px;background-image:linear-gradient(var(--gold),var(--gold));
  background-size:0% 1px;background-repeat:no-repeat;background-position:0 100%;
  transition:background-size var(--dur-3) var(--ease),color var(--dur-2) var(--ease);
}
.link-more:hover{background-size:100% 1px;color:var(--gold)}
.link-more .arw{color:var(--gold);transition:transform var(--dur-2) var(--ease);display:inline-block}
.link-more:hover .arw{transform:translateX(4px)}

/* ---------- Bypass block (skip to content) ----------
   WCAG 2.4.1. Every page opens with the same sticky header and, on the
   generated pages, a nav of eight to ten links. A keyboard or switch user had
   to walk all of them on EVERY page before reaching the content — there was no
   bypass anywhere on the site.

   It is the first focusable thing in <body> and it targets the <main id="main">
   landmark that already exists on every page, so nothing else had to move.

   NOT display:none / visibility:hidden — both remove an element from the focus
   order, which is the one thing this control cannot afford. It is positioned
   off-screen and comes back on :focus, so it stays reachable while staying
   invisible to everyone who is not tabbing.

   z-index rides the --z-* scale (audit_stacking.py fails the build on a raw
   value). --z-toast because a focused skip link must clear the sticky header,
   and the header is the thing it exists to skip. */
.skip-link{
  position:absolute;left:1rem;top:-100%;
  z-index:var(--z-toast);
  display:inline-block;padding:.75rem 1.25rem;
  background:var(--midnight);color:var(--ivory);
  font-family:'Jost',sans-serif;font-size:.9rem;font-weight:400;letter-spacing:.02em;
  text-decoration:none;border:1px solid var(--gold-soft);border-radius:2px;
}
.skip-link:focus{top:1rem}
/* The offset move is the affordance, so it is the one thing that must not be
   animated away for reduced-motion users — there is no transition to disable. */

/* ---------- Nav ---------- */
.nav{position:sticky;top:0;z-index:var(--z-sticky-header);background:transparent;transition:background var(--dur-3) var(--ease),box-shadow var(--dur-3) var(--ease),backdrop-filter var(--dur-3) var(--ease)}
.nav.scrolled{background:rgba(var(--midnight-rgb),.85);backdrop-filter:blur(10px);box-shadow:0 1px 0 rgba(var(--gold-soft-rgb),.18)}
/* Unscrolled, the header is transparent over whatever the hero happens to be.
   The Discover Ocala pasture is bright along its treeline and the nav links sat
   on top of it nearly unreadable; the homepage hero also cycles four photos, so
   this cannot depend on any one image being dark. A soft top-down scrim fixes
   every hero at once without flattening the photograph itself. */
.nav:not(.scrolled)::before{content:"";position:absolute;left:0;right:0;top:0;height:190%;
  background:linear-gradient(180deg,rgba(var(--midnight-deep-rgb),.66) 0%,rgba(var(--midnight-deep-rgb),.34) 55%,rgba(var(--midnight-deep-rgb),0) 100%);
  pointer-events:none;z-index:var(--z-local-under)}
.nav__inner{max-width:var(--max);margin:0 auto;display:flex;align-items:center;justify-content:space-between;padding:1.35rem 2rem}
/* Wordmark: Cormorant Garamond semibold, champagne on midnight (8.8:1). The
   text-shadow only matters in the unscrolled state, where the header is
   transparent over a hero photo and champagne has less headroom than the ivory
   it replaced. */
.nav__brand{font-family:'Cormorant Garamond',serif;font-weight:600;font-size:1.62rem;
  color:var(--gold-soft);letter-spacing:.055em;line-height:1;white-space:nowrap;
  text-shadow:0 1px 12px rgba(var(--midnight-rgb),.55);transition:color var(--dur-2) var(--ease)}
.nav__brand:hover{color:var(--ivory)}
.nav.scrolled .nav__brand{text-shadow:none}
/* PORTAL WORDMARK. "New Construction Ocala" is 22 characters against "Tony
   Gutierrez"'s 14 — 287px versus 176px at the shared 1.62rem, with
   white-space:nowrap holding it on one line. On the main site that leaves a
   46px gap to the phone icon at 375px; on the portal it left ZERO, and pushed
   the hamburger's right edge past the viewport. Every one of the portal's 461
   pages failed the header gate on it and not one main-site page did, which is
   the signature of a brand-length problem rather than a layout one.

   Scaled rather than wrapped: a second line would change the header's height,
   and 74px is a hard constant shared by styles.css, the estimator's scroll
   landing in assets/estimator.js and the stacking gate. The clamp floor is set
   so the wordmark clears the same 46px gap the main site holds at 375px, and
   the ceiling returns it to the shared size once there is room. */
body.is-portal .nav__brand{font-size:clamp(1rem,3.6vw,1.62rem)}
@media (min-width:601px){body.is-portal .nav__brand{font-size:1.62rem}}
.nav__links{display:flex;align-items:center;gap:1.55rem}
.nav__links a{color:var(--ivory);font-family:'Jost',sans-serif;font-weight:300;text-transform:uppercase;letter-spacing:.11em;font-size:.7rem;white-space:nowrap;opacity:.82;transition:opacity var(--dur-2) var(--ease),color var(--dur-2) var(--ease)}
.nav__links a:hover{opacity:1;color:var(--gold-soft)}
.nav__cta{border:1px solid rgba(var(--gold-soft-rgb),.55);color:var(--ivory)!important;padding:.55rem 1.2rem;border-radius:var(--radius);opacity:1!important;transition:background var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease)}
.nav__cta:hover{background:rgba(var(--gold-soft-rgb),.1);border-color:var(--gold-soft)}
.nav__toggle{display:none;background:none;border:none;color:var(--ivory);font-size:1.5rem;cursor:pointer;padding:.2rem;line-height:0}
.nav__toggle svg{width:28px;height:28px;display:block}

/* ---------- Hero ---------- */
.hero{position:relative;min-height:94svh;display:flex;align-items:center;justify-content:center;text-align:center;color:var(--ivory);overflow:hidden;margin-top:-74px;padding-top:74px}
.hero__video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:var(--z-local-behind)}
.hero__overlay{position:absolute;inset:0;z-index:var(--z-local-under);
  background:
    radial-gradient(120% 90% at 50% 40%,rgba(var(--midnight-deep-rgb),.30),rgba(var(--midnight-deep-rgb),.66) 70%,rgba(var(--midnight-deep-rgb),.82)),
    linear-gradient(180deg,rgba(var(--midnight-deep-rgb),.35),rgba(var(--midnight-deep-rgb),.60));
}
.hero__content{max-width:940px;padding:2rem 1.5rem}

/* --- Split hero: brand statement left, live Shortlist card right ---------- */
/* The Camden walkthrough video sits at this depth; nothing else in the hero's
   stacking order depends on what is behind it.                                */
/* Midnight underneath so the split second before the poster decodes is the
   brand's own dark, not white.                                                */
.hero--split .hero__media{position:absolute;inset:0;z-index:var(--z-local-behind);overflow:hidden;
  background:rgb(var(--midnight-deep-rgb))}
/* Left-weighted darkening so the headline holds against a bright Florida sky,
   while the right stays light enough that the card still reads as glass.      */
.hero--split .hero__overlay{
  background:
    linear-gradient(90deg,rgba(var(--midnight-deep-rgb),.82) 0%,rgba(var(--midnight-deep-rgb),.52) 48%,rgba(var(--midnight-deep-rgb),.28) 100%),
    linear-gradient(180deg,rgba(var(--midnight-deep-rgb),.36),rgba(var(--midnight-deep-rgb),.10) 38%,rgba(var(--midnight-deep-rgb),.46));
}
/* Two rows on the left (statement, then buttons); the card spans both. Named
   areas so mobile can reorder the card above the buttons with one line.       */
.hero--split .hero__inner{width:100%;max-width:var(--max);margin:0 auto;padding:2rem 1.5rem;
  display:grid;grid-template-columns:1fr minmax(370px,430px);
  grid-template-areas:"copy card" "btns card";
  gap:1.5rem clamp(2rem,5vw,4rem);align-content:center}
.hero--split .hero__copy{grid-area:copy;text-align:left}
.hero--split .hsl{grid-area:card;align-self:center}
.hero--split .hero__headline{margin:0;text-wrap:balance}
.hero--split .hero__rule{margin:2rem 0}
.hero--split .hero__buttons{grid-area:btns;justify-content:flex-start;margin-top:0}
.hero__lede{font-size:1rem;font-weight:300;line-height:1.75;color:rgba(var(--ivory-rgb),.78);max-width:34em;margin:0}

/* --- The Shortlist, step 1, living in the hero --------------------------- */
/* NOTE: backdrop-filter makes .hsl the containing block for any position:fixed
   descendant. Everything the wizard renders in here is static — keep it that
   way, or a fixed child will silently anchor to this card instead of the page. */
.hsl{position:relative;text-align:left;color:var(--ivory);
  background:rgba(var(--midnight-rgb),.52);
  backdrop-filter:blur(22px) saturate(120%);
  -webkit-backdrop-filter:blur(22px) saturate(120%);
  border:1px solid rgba(var(--gold-soft-rgb),.26);border-radius:var(--radius);
  padding:2rem 2rem 1.5rem;box-shadow:0 40px 90px -42px rgba(var(--black-rgb),.8)}
.hsl__eyebrow{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.28em;
  font-size:0.625rem;font-weight:500;color:var(--gold-soft);margin:0}
.hsl__rule{display:block;width:42px;height:1px;background:var(--gold-soft);opacity:.8;margin:0.75rem 0 1.5rem}
.hsl__body{min-height:224px}
/* pre-JS / JS-off content */
.hsl__title{font-family:'Cormorant Garamond',Georgia,serif;font-size:2rem;font-weight:600;
  color:var(--ivory);line-height:1.16;margin:0 0 0.5rem}
.hsl__sub{font-size:0.875rem;font-weight:300;line-height:1.65;color:rgba(var(--ivory-rgb),.72);margin:0 0 1.5rem}
.hsl__cta{width:100%}
.hsl__alt{display:block;margin-top:1rem;font-family:'Jost',sans-serif;font-size:0.75rem;
  letter-spacing:.12em;color:rgba(var(--ivory-rgb),.58);transition:color var(--dur-2) var(--ease)}
.hsl__alt:hover{color:var(--gold-soft)}
/* progress + honest inventory line */
.hsl__dots{display:flex;gap:0.5rem;margin-top:1.5rem}
.hsl__dots:empty{display:none}
.hsl__stats{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(var(--ivory-rgb),.5);margin:1rem 0 0;padding-top:1rem;font-variant-numeric:tabular-nums;
  border-top:1px solid rgba(var(--ivory-rgb),.12)}

/* Shared wizard chrome, restyled for on-dark glass. Same markup as the overlay. */
.hsl .sl__stepno{color:rgba(var(--ivory-rgb),.86);margin:0 0 0.5rem}
.hsl .sl__q{color:var(--ivory);font-size:1.5rem;margin:0 0 0.25rem}
.hsl .sl__sub{color:rgba(var(--ivory-rgb),.92);font-size:0.75rem;margin:0 0 1rem}
.hsl .sl__opts{gap:0.5rem;margin:1rem 0 1rem}
.hsl .sl__opts--photo{grid-template-columns:1fr}
.hsl .sl__optImg{display:none}          /* the hero background is the imagery */
.hsl .sl__opt{min-height:0;padding:0.75rem 0.75rem;background:rgba(var(--ivory-rgb),.06);
  border-color:rgba(var(--ivory-rgb),.18)}
.hsl .sl__opt:hover{background:rgba(var(--ivory-rgb),.11);border-color:var(--gold-soft);transform:none}
.hsl .sl__opt.is-on{background:rgba(var(--gold-soft-rgb),.20);border-color:var(--gold-soft);
  box-shadow:inset 0 0 0 1px var(--gold-soft)}
.hsl .sl__optLabel{color:var(--ivory);font-size:0.75rem}
.hsl .sl__btn{background:var(--ivory);border-color:var(--ivory);color:var(--midnight);padding:0.75rem 1rem}
.hsl .sl__btn:hover{background:var(--gold-soft);border-color:var(--gold-soft);color:var(--midnight)}
.hsl .sl__btn--ghost{background:none;border-color:rgba(var(--ivory-rgb),.28);color:rgba(var(--ivory-rgb),.8)}
.hsl .sl__btn--ghost:hover{background:none;border-color:var(--gold-soft);color:var(--gold-soft)}
.hsl .sl__dot{background:rgba(var(--ivory-rgb),.2)}
/* Shortlist bands/chips ON THE DARK HERO CARD.
   The rebuild added .sl__band* without hero overrides, so the price figures
   inherited color:var(--midnight) and rendered near-black on a dark glass card —
   effectively invisible. The scrim is 62% midnight rather than a light tint
   because the card sits over a PHOTO: measured against a bright sky behind, 45%
   gives 3.36:1 (fails AA) and 62% gives 5.44:1. */
/* Budget tabs + the Reg Z block on the dark hero card — same on-dark
   translation every other sl__ control gets here, or the midnight-on-midnight
   invisibility bug above repeats on the new controls. */
.hsl .sl__tab{color:var(--ivory);background:rgba(var(--midnight-rgb),.55);border-color:rgba(var(--ivory-rgb),.28)}
.hsl .sl__tab:hover{border-color:var(--gold-soft)}
.hsl .sl__tab.is-on{color:var(--ivory);background:rgba(var(--gold-soft-rgb),.22);border-color:var(--gold-soft);box-shadow:inset 0 0 0 1px var(--gold-soft)}
.hsl .regz{border-color:rgba(var(--ivory-rgb),.24);background:rgba(var(--midnight-rgb),.45)}
.hsl .regz__terms{color:rgba(var(--ivory-rgb),.92)}
.hsl .regz__standing{color:rgba(var(--ivory-rgb),.78)}
.hsl .sl__band{background:rgba(var(--midnight-rgb),.62);border-color:rgba(var(--ivory-rgb),.24)}
.hsl .sl__band:hover{background:rgba(var(--midnight-rgb),.72);border-color:var(--gold-soft);transform:none}
.hsl .sl__band.is-on{background:rgba(var(--gold-soft-rgb),.28);border-color:var(--gold-soft)}
.hsl .sl__bandLabel{color:var(--ivory);font-size:1rem;font-weight:400}
.hsl .sl__bandSub{color:rgba(var(--ivory-rgb),.92)}
.hsl .sl__bandN{color:rgba(var(--ivory-rgb),.92)}
.hsl .sl__label{color:var(--gold-soft)}
.hsl .sl__skip{color:rgba(var(--ivory-rgb),.82);border-color:rgba(var(--ivory-rgb),.34)}
.hsl .sl__skip:hover{color:var(--gold-soft);border-color:var(--gold-soft)}
.hsl .sl__optFrom{color:rgba(var(--ivory-rgb),.92)}
.hsl .sl__optN{color:rgba(var(--ivory-rgb),.92)}
.hsl .sl__bands{gap:0.5rem;margin:1rem 0 1rem}
/* Homepage split hero is always a photo (crossfading stills) — ivory, per above. */
.hero__eyebrow{display:block;margin-bottom:2rem;color:var(--ivory)}
/* Headline is now the hero focal point — elegant serif, homes-first */
.hero__headline{font-family:'Cormorant Garamond',Georgia,serif;color:var(--ivory);font-weight:500;font-size:clamp(1.7rem,4.4vw,3.15rem);letter-spacing:.015em;line-height:1.18;max-width:none;margin:0 auto;text-wrap:balance}
.hero__rule{display:block;width:64px;height:1px;background:var(--gold-soft);margin:3rem auto;opacity:.9}
/* Buttons are the point of the hero — give them presence */
.hero__buttons{display:flex;gap:1rem;justify-content:center;flex-wrap:wrap;margin-top:1rem}
.hero__buttons .btn{padding:1rem 2rem;font-size:0.75rem}
.hero__scroll{position:absolute;bottom:2rem;left:50%;transform:translateX(-50%);display:flex;flex-direction:column;align-items:center;gap:0.75rem;color:var(--gold-soft);font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.28em;font-size:0.75rem}
.hero__scroll::after{content:"";width:1px;height:34px;background:linear-gradient(var(--gold-soft),transparent)}
@media (prefers-reduced-motion:no-preference){
  .hero__scroll::after{animation:drift 2.4s var(--ease) infinite}
}
@keyframes drift{0%,100%{opacity:.3;transform:scaleY(.7)}50%{opacity:1;transform:scaleY(1)}}
/* Hero on phones: keep the eyebrow + headline from overflowing narrow screens */
@media (max-width:560px){
  .hero__eyebrow{letter-spacing:.16em;font-size:0.625rem;margin-bottom:1.5rem}
  .hero__headline{font-size:1.5rem;line-height:1.24;text-wrap:wrap}
  .hero__rule{margin:2rem auto}
  .hero__buttons .btn{padding:1rem 2rem}
}
/* Split hero stacks — and the card jumps AHEAD of the buttons so the thing
   you're meant to use is in the first screenful, not below three CTAs.
   Height goes fluid so a tall step (six options) can't overflow the viewport. */
@media (max-width:980px){
  .hero--split{min-height:0;padding-bottom:3rem;align-items:flex-start}
  /* CTA sits ABOVE the card on phones. Below it, its position depended on how
     tall the current wizard step was, and on a 360x740 screen that landed the
     primary CTA underneath the sticky Call/Text bar (measured: CTA 665-712,
     callbar 685-740). Above the card it is always in the top half. */
  .hero--split .hero__inner{grid-template-columns:1fr;
    grid-template-areas:"copy" "btns" "card";gap:2rem;padding-top:3rem}
  .hero--split .hero__copy{text-align:center}
  .hero--split .hero__rule{margin:1.5rem auto}
  .hero--split .hero__buttons{justify-content:center}
  .hero--split .hero__lede{margin:0 auto}
  .hero--split .hero__scroll{display:none}
}
@media (max-width:560px){
  /* gap tuned so the CTA's bottom stays clear of the fixed chat launcher
     (measured: launcher top 700px on a 375x812 screen) */
  .hero--split .hero__inner{padding:1rem 1rem 0;gap:1rem}
  /* the card's own copy says this better, and 90px of vertical is worth more */
  .hero--split .hero__lede{display:none}
  .hero--split .hero__rule{margin:1rem auto}
  /* Only the inventory link goes — it's the very next section and it's in the
     menu. "Schedule a Visit" STAYS: it is the homepage's only trigger for the
     visit modal, and hiding the whole row made that modal unreachable on phones
     entirely. (It is also now in the mobile menu, so it survives any scroll
     position.) One full-width button keeps the row short enough not to fight
     the chat launcher the way two did. */
  .hero--split .hero__buttons{gap:0.5rem}
  .hero--split .hero__buttons .btn--ghost{display:none}
  .hero--split .hero__buttons .btn{width:100%;padding:1rem 1.5rem;font-size:0.75rem;letter-spacing:.14em}
  .hsl{padding:1rem 1rem 1rem}
  .hsl__rule{margin:0.75rem 0 1rem}
  .hsl__body{min-height:200px}
  .hsl__title{font-size:1.5rem}
  .hsl__dots{margin-top:1rem}
  .hsl__stats{margin-top:0.75rem;padding-top:0.75rem}
  .hsl .sl__q{font-size:1.25rem}
}

/* ---------- Sections ---------- */
.section{max-width:var(--max);margin:0 auto;padding:6rem 2rem}
.section--tint{max-width:none;background:var(--cream);padding-left:0;padding-right:0}
.section--tint > *{max-width:var(--max);margin-left:auto;margin-right:auto;padding-left:2rem;padding-right:2rem}
.section__head{text-align:center;max-width:620px;margin:0 auto 4rem}
.section__eyebrow{display:block;margin-bottom:1rem}
.section__title{font-size:clamp(2.2rem,4.5vw,3.2rem);font-weight:500;letter-spacing:.005em}
.section__head .section__title::after{content:"";display:block;width:54px;height:1px;background:var(--gold);margin:1.5rem auto 0}
.section__sub{color:var(--muted);margin-top:1.5rem;font-size:1rem;font-weight:300}
/* Book a Community Tour (/partners) — Cal.com popup, one trigger, no inline
   calendar. Generous vertical air sets the booking CTA apart as its own beat.
   Layout only: the button is a plain .btn--solid and the focus ring comes from
   the global :focus-visible rule, so no colour is restated here. */
.section--book{padding-top:7.5rem;padding-bottom:7.5rem;text-align:center}
.section--book .section__head{margin-bottom:2.5rem}
/* WRAPS. On /partners this row holds one button and never needed to; the home
   detail pages put three side by side (book / text / call) and at 375px they
   summed to 457px and spilled the viewport. Wrapping is the fix that keeps both
   pages on one rule instead of forking the component. */
.section__book-cta{display:flex;justify-content:center;flex-wrap:wrap;gap:.75rem}
@media (max-width:640px){.section--book{padding-top:5rem;padding-bottom:5rem}}
/* LEAD POSITION ONLY — booking now opens /partners, directly under the hero.
   The 7.5rem above was tuned for a section with cream on both sides; between the
   full-bleed hero and the dark quick-access bar the same value reads as two dead
   bands: 120px of empty cream before the eyebrow, and the CTA floating 120px
   above a hard colour edge. The adjacent-sibling selector keeps this to the
   section in that position — .section--book's own rule is untouched, so the
   block is unchanged anywhere it is not leading a page. */
.page-hero + .section--book{padding-top:4.5rem;padding-bottom:5rem}
@media (max-width:640px){.page-hero + .section--book{padding-top:3rem;padding-bottom:3.25rem}}

/* ---------- Community map entry (community pages) ----------
   Sits directly under the hero. Two entries at most — the builder's site plan
   (opens the brochure lightbox) and, on spot-lot communities, the interactive
   pin map further down. Both are the same control shape so neither reads as the
   primary; the labels carry the difference. */
/* ---- HOA dues, community pages ------------------------------------------
   Informational block. One row per DISTINCT due amount, labelled by the series
   and product line it covers. CDD is deliberately absent — it is an estimator
   input, not a display figure. */
.hoa{padding-top:3rem;padding-bottom:0}
.hoa__inner{max-width:var(--max);margin:0 auto;padding:0 2rem}
.hoa__eyebrow{text-align:center;margin-bottom:1.25rem}
.hoa__rows{display:flex;flex-wrap:wrap;gap:.75rem;justify-content:center}
.hoa__row{display:flex;flex-direction:column;align-items:center;gap:.15rem;
  min-width:11rem;padding:1rem 1.35rem;border:1px solid var(--line);
  border-radius:var(--radius);background:var(--cream)}
.hoa__amt{font-family:'Cormorant Garamond',Georgia,serif;font-size:1.55rem;
  line-height:1.1;color:var(--ink);font-weight:500}
.hoa__per{font-family:'Jost',sans-serif;font-size:.7rem;letter-spacing:.1em;
  color:var(--muted);margin-left:.15rem}
.hoa__ser{font-family:'Jost',sans-serif;text-transform:uppercase;
  letter-spacing:.13em;font-size:.625rem;color:var(--gold);font-weight:500;
  text-align:center}
.hoa__none{text-align:center;font-size:1.05rem;color:var(--ink)}
.hoa__note{margin-top:1rem;text-align:center;font-size:.8rem;color:var(--muted);
  font-weight:300;line-height:1.7;max-width:44rem;margin-left:auto;margin-right:auto}
@media(max-width:600px){.hoa__row{min-width:0;flex:1 1 8.5rem;padding:.8rem .6rem}
  .hoa__amt{font-size:1.3rem}}

.cmap{padding-top:3rem;padding-bottom:0}
.cmap__eyebrow{text-align:center;margin-bottom:1.25rem}
.cmap__row{display:flex;gap:1rem;justify-content:center;flex-wrap:wrap}
.cmap__item{display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto auto;
  gap:0 .9rem;align-items:center;text-align:left;
  min-width:min(320px,100%);padding:1.05rem 1.35rem;
  background:var(--cream);border:1px solid rgba(var(--midnight-rgb),.10);border-radius:2px;
  color:inherit;text-decoration:none;cursor:pointer;font:inherit;
  transition:border-color var(--dur-2) ease,transform var(--dur-2) ease}
.cmap__item:hover{border-color:var(--gold);transform:translateY(-2px)}
.cmap__ico{grid-row:1/4;width:30px;height:30px;color:var(--gold)}
.cmap__label{font-weight:500;letter-spacing:.01em}
.cmap__sub{color:var(--muted);font-size:.86rem;font-weight:300}
.cmap__go{color:var(--gold);font-size:.82rem;letter-spacing:.06em;text-transform:uppercase;margin-top:.3rem}
@media (max-width:640px){
  .cmap{padding-top:2rem}
  .cmap__item{min-width:100%;padding:.95rem 1.1rem}
}

/* Product type on a card's identity line — present on every home and plan card.
   Same weight as the rest of the line: it is a fact, not a badge. */
.home__type,.plan__type{white-space:nowrap}

/* ---------- Home card -> home detail page ----------
   The identity-line anchor stretches over the whole card, so image, price and
   title all click through while only ONE link lands in the accessibility tree.
   Anything the buyer must still be able to press — carousel arrows and dots, the
   action row, the brochure/video buttons — is lifted above the overlay. Without
   these z-index lines the stretched link silently eats every control on the card. */
.home{position:relative}
.home__jump{color:inherit;text-decoration:none}
.home__jump::after{content:"";position:absolute;inset:0;z-index:var(--z-local-raise)}
.home:hover .home__jump{color:var(--gold)}
.home__actions,.home__assets{position:relative;z-index:var(--z-local-over)}
.home__media .hcar__arw,.home__media .hcar__dots{z-index:var(--z-local-control)}

/* ---------- Home detail page ---------- */
.hd{max-width:var(--max);margin:0 auto;padding:var(--sp-6) var(--sp-6) 0}
/* .hd__grid is GONE. It was the two-column hero — gallery beside the price —
   and the 2026-08-02 restructure split those into two sections so the whole
   identity block can sit above the fold at 375px. The rule is deleted rather
   than left orphaned: a dead layout rule is the thing a later edit reattaches
   by accident. */

/* ---- the identity block: everything above the fold, in answer order ---- */
.hd--ident{padding-bottom:var(--sp-5)}
.hd--ident .hd__head{display:flex;flex-direction:column;align-items:flex-start}
/* The text stack keeps a readable measure at 1440 instead of stretching a
   price and a plan name across 1200px; the stat strip below it deliberately
   does NOT — it is a strip, and it wants the full width to stay one row. */
.hd--ident .hd__crumb,.hd--ident .hd__badges,.hd--ident .hd__price,
.hd--ident .hd__payunit,.hd--ident .hd__ident,.hd--ident .hd__sub{max-width:60ch}
.hd--ident .hd__facts{width:100%;margin-top:var(--sp-5)}
/* The payment sits directly under the price it qualifies, and reads louder
   here than on a card: this is the page a buyer opened to see it. */
.hd__payunit{margin:var(--sp-3) 0 0}
.hd__payunit .home__payamt{font-size:1.375rem}
.hd__payunit .home__payterms,.hd__payunit .home__paydisc{max-width:56ch}
.hd--gallery{padding-top:var(--sp-6);padding-bottom:0}
.hd__media,.hd__media--ph{position:relative;aspect-ratio:4/3;overflow:hidden;border-radius:2px;background:var(--midnight)}
.hd__media img{width:100%;height:100%;object-fit:cover;display:block}
.hd__media--ph{display:grid;place-items:center;color:var(--ivory)}
/* Breadcrumb on a LIGHT background. .crumb is champagne-on-photo and belongs to
   .page-hero; reusing it here put #cbb489 on #f7f3ec — 1.82:1, well under the
   4.5 small-text minimum, on all 392 pages. The contrast gate caught it. This
   variant is 16:1 and keeps the same type treatment. */
.hd__crumb{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.2em;
  font-size:.75rem;color:var(--midnight);margin-bottom:1.25rem;display:inline-block}
.hd__crumb a{color:var(--midnight);text-underline-offset:3px;text-decoration:underline}
.hd__crumb a:hover{color:var(--gold)}
.hd__badges{display:flex;gap:.5rem;flex-wrap:wrap;margin:.9rem 0}
/* .badge is position:absolute/right:1rem by default — it is built to overlay a
   card's photo. In this inline row it must be a normal flow item, exactly as
   .home__badges already does it. Without this reset the badges anchored to the
   nearest positioned ancestor (none) and parked 1rem from the VIEWPORT edge:
   at 1024px they ended at 1008, 8px past the content limit, on every home page.
   The proportion gate caught it. */
.hd__badges .badge{position:static;top:auto;right:auto;left:auto}
/* The price ceiling came down from 2.8rem to 2.4rem when the payment line and
   the stat strip joined it above the fold. Measured, not guessed: at 375x812
   the old ceiling put the last stat cell 46px below the fold on the tallest
   homes (8 stats, two-line move-in). Nothing else in the block had slack. */
.hd__price{font-size:clamp(1.9rem,3.4vw,2.4rem);font-weight:500;letter-spacing:.005em;line-height:1.15}
.hd__ident{font-size:1.05rem;font-weight:400;line-height:1.5;margin-top:var(--sp-4)}
.hd__sub{color:var(--muted);margin-top:var(--sp-1)}
/* THE SPEC STRIP. The hairlines between cells used to be the CONTAINER's own
   dark background showing through a 1px gap. That works only while the cells
   fill every track — the moment the count doesn't divide by the column count
   (8 facts in a 7-wide row) the leftover track paints as a solid grey band
   instead of an empty tile. Each cell now draws its own hairline with a
   spread-only box-shadow, which cannot affect layout or scroll width, and the
   container is ivory so any leftover track reads as blank. 140px (not 150) so
   all eight facts still land in one row at desktop. */
.hd__facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1px;
  background:var(--ivory);border:1px solid rgba(var(--midnight-rgb),.10)}
.hd__fact{background:var(--ivory);padding:var(--sp-3) var(--sp-4);
  box-shadow:0 0 0 1px rgba(var(--midnight-rgb),.10)}
/* --muted is 3.68:1 and below AA for text you have to read. These labels name
   what the number means, so they use --muted-aa like every other informational
   small text on the site. */
.hd__fact dt{color:var(--muted-aa);font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;line-height:1.3}
.hd__fact dd{margin-top:var(--sp-1);font-size:1rem;line-height:1.3}
/* Community map with THIS homesite marked. The marker's left/top come from the
   map PDF's own text layer (measured at ingest), so it lands on the printed lot
   number rather than near it. Percentage positioning means it stays correct at
   every width without re-measuring. */
.hd__map{margin:0 auto 2rem;max-width:820px}
.hd__mapBtn{display:block;position:relative;width:100%;padding:0;border:1px solid rgba(var(--midnight-rgb),.12);
  background:var(--ivory);cursor:pointer;border-radius:2px;overflow:hidden}
.hd__mapBtn img{display:block;width:100%;height:auto}
.hd__pin{position:absolute;transform:translate(-50%,-50%);z-index:var(--z-local-raise);
  min-width:26px;height:26px;padding:0 6px;border-radius:13px;
  background:var(--gold);color:var(--midnight);border:2px solid var(--ivory);
  display:grid;place-items:center;font-size:.72rem;font-weight:600;
  box-shadow:0 1px 6px rgba(0,0,0,.35);pointer-events:none}
.hd__pin::after{content:"";position:absolute;inset:-7px;border-radius:50%;
  border:2px solid var(--gold);opacity:.55}
.hd__map figcaption{margin-top:.7rem;text-align:center;color:var(--muted);font-size:.9rem}
@media (max-width:640px){ .hd__pin{min-width:22px;height:22px;font-size:.66rem} }

.hd__assets{display:flex;gap:.75rem;flex-wrap:wrap;justify-content:center}
.hd__form{max-width:620px;margin:2.5rem auto 0;text-align:left}
.hd__soldbtns{display:flex;gap:.75rem;justify-content:center;flex-wrap:wrap;margin-top:1.5rem}
.hd__sold{padding-top:5rem}
@media (max-width:900px){
  .hd{padding:var(--sp-5) var(--sp-5) 0}
  .hd__facts{grid-template-columns:repeat(auto-fit,minmax(130px,1fr))}
}
/* PHONE: the strip goes THREE columns, not two. Two columns of 8 stats is four
   rows ~62px tall — 248px of the 738px a 375x812 phone has under the header,
   which is what pushed the last cell below the fold. Three columns is three
   rows, and the longest value in the set ("≈10,020 sq ft") still fits a 103px
   cell at this size. Below 340px it falls back to two rather than truncating. */
@media (max-width:640px){
  .hd--ident .hd__facts{grid-template-columns:repeat(auto-fit,minmax(96px,1fr))}
  .hd__fact{padding:var(--sp-2) var(--sp-3)}
  .hd__fact dt{font-size:.66rem;letter-spacing:.06em}
  .hd__fact dd{font-size:.92rem}
  .hd__payunit .home__payamt{font-size:1.25rem}
}

/* ---------- This Home's Actual Costs ---------- */
/* Three fixed costs, each with the reason it is that number. The "why" column
   is the point of the section: a property-tax figure with no rate beside it is
   a number a buyer has to take on faith, and this page's whole premise is that
   these three are the ones they do not have to. */
.hcost{max-width:760px;margin:0 auto;border:1px solid rgba(var(--midnight-rgb),.10)}
.hcost__row{display:grid;grid-template-columns:minmax(0,1fr) auto;
  column-gap:var(--sp-5);row-gap:var(--sp-1);padding:var(--sp-4) var(--sp-5);
  align-items:baseline}
.hcost__row + .hcost__row{border-top:1px solid rgba(var(--midnight-rgb),.10)}
.hcost__k{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.09em;
  font-size:.75rem;color:var(--muted-aa)}
.hcost__v{font-size:1.15rem;font-weight:500;text-align:right;white-space:nowrap}
.hcost__why{grid-column:1 / -1;margin:0;font-size:.82rem;color:var(--muted-aa);line-height:1.5}
.hcost__note{max-width:760px;margin:var(--sp-4) auto 0;font-size:.82rem;
  color:var(--muted-aa);line-height:1.6;text-align:center}
@media (max-width:640px){
  .hcost__row{padding:var(--sp-3) var(--sp-4);column-gap:var(--sp-3)}
  .hcost__v{font-size:1.05rem}
}


/* ---------- Grids ---------- */
.grid{display:grid;gap:2rem}
.grid--3{grid-template-columns:repeat(3,1fr)}
.grid--4{grid-template-columns:repeat(4,1fr)}

/* ---------- Community cards ---------- */
.card{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow);transition:transform var(--dur-3) var(--ease),box-shadow var(--dur-3) var(--ease)}
.card:hover{transform:translateY(-6px);box-shadow:var(--shadow-lift)}
.card__media{position:relative;aspect-ratio:4/3;overflow:hidden}
.card__media img{transition:transform 1.1s var(--ease)}
.card:hover .card__media img{transform:scale(1.06)}
.card__tag{position:absolute;top:1rem;left:1rem;background:rgba(var(--midnight-rgb),.72);backdrop-filter:blur(4px);color:var(--ivory);font-family:'Jost',sans-serif;font-weight:400;font-size:0.625rem;padding:0.5rem 0.75rem;border:1px solid rgba(var(--gold-soft-rgb),.4);border-radius:var(--radius);text-transform:uppercase;letter-spacing:.22em}
.card__body{padding:2rem 2rem 2rem}
.card__title{font-size:1.5rem;font-weight:600}
/* Image and name are both routes to the community page. The image link fills
   its box so the whole photo is the target; the name underlines on hover so it
   reads as a link and not just a heading that happens to be clickable. */
.card__imglink{position:absolute;inset:0;display:block;cursor:pointer}
.card__media--ph .card__imglink{display:flex;align-items:center;justify-content:center}
.card__title a{color:inherit;text-decoration:none;cursor:pointer;background-image:linear-gradient(var(--gold),var(--gold));background-repeat:no-repeat;background-position:0 92%;background-size:0 1px;transition:background-size var(--dur-3) var(--ease),color var(--dur-3) var(--ease)}
.card:hover .card__title a,.card__title a:hover{background-size:100% 1px}
.card__title a:hover{color:var(--gold-deep,var(--gold-deep))}
.card__imglink:focus-visible,.card__title a:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.card__meta{color:var(--muted);font-size:0.875rem;text-transform:uppercase;letter-spacing:.12em;margin:0.5rem 0 1rem}
.card__price{font-family:'Cormorant Garamond',serif;color:var(--midnight);font-weight:600;font-size:1.5rem}
/* HOA beneath the price — same label treatment as "From", quieter figure. */
.card__hoa{font-family:'Jost',sans-serif;font-size:0.8rem;color:var(--ink);margin:.1rem 0 0;font-variant-numeric:tabular-nums}
.card__hoa span{font-size:0.7rem;letter-spacing:.08em;text-transform:uppercase;color:var(--muted-aa);margin-right:.3rem}
.card__price span{color:var(--gold);font-size:1rem;font-family:'Jost',sans-serif;font-weight:400;letter-spacing:.05em}
.card__specs{font-size:0.875rem;color:var(--muted);margin:0.25rem 0 1.5rem;font-weight:300}
.card__divider{height:1px;background:var(--line);margin:0 0 1.5rem}

/* ---------- Quick move-in homes ---------- */
.home{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow);transition:transform var(--dur-3) var(--ease),box-shadow var(--dur-3) var(--ease)}
.home:hover{transform:translateY(-6px);box-shadow:var(--shadow-lift)}
.home__media{position:relative;aspect-ratio:16/10;overflow:hidden}
.home__media img{transition:transform 1.1s var(--ease)}
.home:hover .home__media img{transform:scale(1.06)}
.badge{position:absolute;top:1rem;right:1rem;background:rgba(var(--midnight-rgb),.72);backdrop-filter:blur(4px);color:var(--ivory);font-family:'Jost',sans-serif;font-weight:400;font-size:0.625rem;padding:0.5rem 0.75rem;border:1px solid rgba(var(--gold-soft-rgb),.4);border-radius:var(--radius);text-transform:uppercase;letter-spacing:.22em}
.badge--uc{border-color:rgba(var(--gold-soft-rgb),.7);color:var(--gold-soft)}
.home__body{padding:2rem 2rem 2rem}
.home__price{font-family:'Cormorant Garamond',serif;font-weight:600;font-size:2rem;color:var(--midnight)}

/* A2 — THE PAYMENT UNIT ON EVERY CARD.
   Figure, terms and disclosure are one visual block because they are one legal
   unit: a stated monthly payment is a Reg Z triggering term and its terms must
   be read WITH it, not after a scroll. Hence no collapse, no tooltip, no
   "details" — and a left rule tying the three lines together so the eye reads
   them as one thing rather than three stacked paragraphs. */
.home__pay-unit{margin:0.35rem 0 0.75rem;padding:0 0 0 0.7rem;
  border-left:2px solid rgba(var(--gold-soft-rgb),.55)}
.home__payfig{display:flex;align-items:baseline;flex-wrap:wrap;gap:0.4rem;margin:0}
/* THE AMOUNT AND ITS UNIT ARE ONE TOKEN. "$1,847" wrapping away from "/mo"
   states a different number than the one intended, so this never breaks —
   build/audit_token_integrity.py asserts it at 375/768/1280. */
.home__payamt{font-family:'Jost',sans-serif;font-size:1.125rem;font-weight:600;
  letter-spacing:.01em;color:var(--midnight);white-space:nowrap}
.home__paylbl{font-family:'Jost',sans-serif;font-size:0.7rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted-aa);white-space:nowrap}
.home__payterms{margin:0.2rem 0 0;font-family:'Jost',sans-serif;font-size:0.7rem;
  line-height:1.55;letter-spacing:.01em;color:var(--muted-aa)}
/* Kept for any non-figure <b> a future terms line might carry. The rate and
   the APR are NOT bold and no longer use <b> at all — they render through
   .regz__eq, plain and equal. See that rule for why. */
.home__payterms b{font-weight:600;color:var(--ink);white-space:nowrap}
.home__paydisc{margin:0.25rem 0 0;font-family:'Jost',sans-serif;font-size:0.64rem;
  line-height:1.5;letter-spacing:.01em;color:var(--muted-aa)}
@media (max-width:400px){
  .home__payamt{font-size:1.05rem}
  .home__paydisc{font-size:0.62rem}
}
/* THE IDENTITY LINE. One size for both lines and every surface — see
   _ident_line() in build/generate.py for why the structure exists. The size
   dropped from .875rem to .8125rem and the tracking from .12em to .09em when
   the line became two lines: the same text now has two line-boxes to live in,
   so it does not need the extra width, and the narrower setting is what buys
   "Silver Springs Shores" its no-wrap guarantee inside a 375px card. */
.home__address{font-size:0.8125rem;text-transform:uppercase;letter-spacing:.09em;
  margin:0.5rem 0 1rem;line-height:1.45}
.home__ident-comm{display:block;color:var(--midnight);font-weight:500;
  /* NOWRAP IS THE GUARANTEE, ellipsis is the seatbelt. The longest community
     name measures ~200px against ~270px of card at 375px, so the ellipsis is
     unreachable today; it exists so a future 30-character community truncates
     visibly instead of blowing the card's width out sideways. */
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.home__ident-meta{display:block;color:var(--muted-aa);font-weight:400}
/* Each token is atomic. The only breakable whitespace on line 2 is the single
   space between these two spans, which is the phrase boundary. */
.home__ident-plan,.home__ident-meta .home__type{white-space:nowrap}
.home:hover .home__ident-comm{color:var(--gold)}
.home__specs{list-style:none;display:flex;gap:1.5rem;flex-wrap:wrap;font-size:0.75rem;font-weight:400;text-transform:uppercase;letter-spacing:.1em;color:var(--ink);border-top:1px solid var(--line);padding-top:1rem}
.home__specs li{position:relative}
.home__specs li:not(:last-child)::after{content:"";position:absolute;right:-.75rem;top:50%;width:1px;height:12px;transform:translateY(-50%);background:var(--gold);opacity:.5}
.home__note{margin-top:1rem;font-size:0.75rem;text-transform:uppercase;letter-spacing:.12em;color:var(--gold)}
.home__link{display:inline-block;margin-top:1.5rem}

/* ---------- Floor plans ---------- */
/* Column layout so the action row can be pinned to the card's foot. The
   "Offered in" list runs 1–6 lines depending on the plan, which left the
   brochure buttons stepping up and down across a row. */
.plan{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow);transition:transform var(--dur-3) var(--ease),box-shadow var(--dur-3) var(--ease);display:flex;flex-direction:column}
.plan:hover{transform:translateY(-6px);box-shadow:var(--shadow-lift)}
.plan__media{aspect-ratio:4/3;background:var(--cream);overflow:hidden}
.plan__media img{object-fit:cover;transition:transform 1.1s var(--ease)}
.plan:hover .plan__media img{transform:scale(1.06)}
.plan__body{padding:1.5rem 1.5rem 2rem;flex:1;display:flex;flex-direction:column}
.plan__title{font-size:1.5rem;font-weight:600}
.plan__specs{color:var(--muted);font-size:0.75rem;text-transform:uppercase;letter-spacing:.1em;margin:0.5rem 0 0.75rem}
.plan__price{font-family:'Cormorant Garamond',serif;color:var(--midnight);font-weight:600;font-size:1.5rem}
.plan__tag{margin-top:0.5rem;font-size:0.75rem;color:var(--muted);line-height:1.5;font-weight:300}

/* Floor-plan video-tour button */
.plan__media{position:relative;display:block;width:100%;padding:0;border:0;cursor:pointer}
button.plan__media{cursor:pointer}
.plan__play{position:absolute;bottom:1rem;left:1rem;background:rgba(var(--midnight-rgb),.78);backdrop-filter:blur(4px);color:var(--ivory);font-family:'Jost',sans-serif;font-weight:400;font-size:0.75rem;text-transform:uppercase;letter-spacing:.16em;padding:0.5rem 1rem;border:1px solid rgba(var(--gold-soft-rgb),.4);border-radius:var(--radius);display:inline-flex;align-items:center;gap:0.5rem;transition:background var(--dur-2) var(--ease),color var(--dur-2) var(--ease)}
.plan__play svg{width:11px;height:11px}
button.plan__media:hover .plan__play{background:var(--gold);color:var(--midnight);border-color:var(--gold)}

/* ---------- Why buy with me ---------- */
.why{display:grid;grid-template-columns:auto 1fr;gap:4rem;align-items:center}
.why__photo{position:relative;width:300px;aspect-ratio:4/5;flex:0 0 auto}
.why__photo img{border-radius:var(--radius);position:relative;z-index:var(--z-local-raise)}
/* Thin gold gallery frame, offset behind the portrait */
.why__photo::before{content:"";position:absolute;inset:0;transform:translate(16px,16px);border:1px solid var(--gold);border-radius:var(--radius);z-index:var(--z-local-base)}
.why__content .section__eyebrow{display:block;margin-bottom:1rem}
.why__content .section__title{font-size:clamp(2rem,4vw,2.8rem)}
.why__content .section__title::after{content:"";display:block;width:54px;height:1px;background:var(--gold);margin:1.5rem 0 0}
.why__list{list-style:none;display:grid;gap:2rem;margin-top:2rem}
.why__list li{display:flex;gap:1.5rem;align-items:flex-start}
.why__icon{flex:0 0 auto;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border:1px solid var(--gold);border-radius:50%;color:var(--gold)}
.why__icon svg{width:19px;height:19px}
.why__list h3{font-size:1.5rem;font-weight:600;margin-bottom:0.25rem}
.why__list p{color:var(--muted);font-size:1rem;font-weight:300}

/* ---------- Contact ---------- */
/* Honeypot: pulled off-screen (not display:none, which naive bots skip) */
.hp{position:absolute!important;left:-9999px;width:1px;height:1px;overflow:hidden}
.contact{display:grid;grid-template-columns:1.35fr 1fr;gap:3rem;align-items:start}
.contact__form{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);padding:3rem;box-shadow:var(--shadow);display:grid;gap:1.5rem}
.contact__form label{display:grid;gap:0.5rem;font-family:'Jost',sans-serif;font-weight:500;text-transform:uppercase;letter-spacing:.16em;font-size:0.75rem;color:var(--midnight)}
.contact__form input,.contact__form textarea{
  font-family:'Jost',sans-serif;font-weight:300;font-size:1rem;letter-spacing:.01em;
  padding:1rem 1rem;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--ivory);color:var(--ink);transition:border-color var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease);
}
.contact__form input::placeholder,.contact__form textarea::placeholder{color:var(--placeholder);text-transform:none;letter-spacing:normal}
.contact__form input:focus,.contact__form textarea:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(var(--gold-rgb),.12)}
.contact__form .btn{margin-top:0.5rem}
.contact__note{font-family:'Jost',sans-serif;font-size:0.875rem;font-weight:400;letter-spacing:.04em;text-align:center;min-height:1.2em}
.contact__side{background:var(--midnight);color:var(--ivory);border-radius:var(--radius);padding:3rem;display:grid;gap:1rem;align-content:start}
.contact__side h3{color:var(--ivory);font-size:1.5rem;font-weight:600;margin-bottom:0.75rem}
.contact__side .btn{justify-content:flex-start}
.contact__hours{margin-top:1.5rem;padding-top:1.5rem;border-top:1px solid rgba(var(--gold-soft-rgb),.25);font-size:0.875rem;font-weight:300;opacity:.85;line-height:1.7}
.contact__hours p{margin:0}
.contact__hours strong{font-family:'Jost',sans-serif;font-weight:500;text-transform:uppercase;letter-spacing:.16em;font-size:0.625rem;color:var(--gold-soft)}

/* ---------- Footer ---------- */
.footer{background:var(--midnight);color:rgba(var(--ivory-rgb),.7);padding:4rem 2rem 2rem}
.footer a{color:rgba(var(--ivory-rgb),.7);transition:color var(--dur-2) var(--ease)}
.footer a:hover{color:var(--gold-soft)}
.footer__grid{max-width:var(--max);margin:0 auto;display:grid;grid-template-columns:repeat(3,1fr);gap:2rem}
.footer h4{color:var(--ivory);margin-bottom:1rem;font-size:0.75rem;font-family:'Jost',sans-serif;font-weight:500;text-transform:uppercase;letter-spacing:.2em}
.footer__brand{font-family:'Cormorant Garamond',serif!important;font-size:1.5rem!important;font-weight:600!important;text-transform:none!important;letter-spacing:.03em!important;color:var(--ivory)!important}
.footer p{font-weight:300;font-size:0.875rem;line-height:1.9}
.footer__social{list-style:none;display:grid;gap:0.5rem;font-size:0.75rem;text-transform:uppercase;letter-spacing:.14em;font-weight:300}
.footer__social a{display:inline-flex;align-items:center;gap:0.5rem}
.footer__social svg{width:17px;height:17px;flex:0 0 auto}
.footer__eho{display:flex;flex-direction:column;align-items:flex-start;gap:0.75rem}
.footer__eho-logo{width:46px;height:46px;object-fit:contain;opacity:.8}
.footer__eho p{text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem}
.footer__disclaimer{max-width:var(--max);margin:3rem auto 0;padding-top:2rem;border-top:1px solid rgba(var(--gold-soft-rgb),.16);font-size:0.75rem;color:rgba(var(--ivory-rgb),.42);line-height:1.8;font-weight:300}
.footer__disclaimer p{margin-bottom:0.75rem}
/* PORTAL SKIN ONLY (newconstructionocalafl.com). Operator identification and
   data provenance. Deliberately brighter than the rest of the fine print: on a
   product-first brand this is the line that says who is behind the site, and
   burying it at .42 opacity with the copyright would be disclosure in name
   only. Emitted by build/portal.py; absent from the main skin, which names
   Tony in the footer heading already. */
.footer__operator{color:rgba(var(--ivory-rgb),.78);font-size:0.8rem}
.footer__source{color:rgba(var(--ivory-rgb),.62);font-size:0.78rem}
/* The footer never had a mobile breakpoint — it stayed repeat(3,1fr) at every
   width, and grid items' min-width:auto widened the tracks until the Equal
   Housing column sat at 471px on a 375px screen, i.e. entirely off-screen.
   html/body overflow-x:clip hid the sideways scroll, so it just vanished. */
@media (max-width:760px){
  .footer__grid{grid-template-columns:1fr;gap:2rem}
  .footer__grid > *{min-width:0}
}

/* ---------- Sticky mobile call bar ---------- */
.mobile-callbar{display:none;position:fixed;bottom:0;left:0;right:0;z-index:var(--z-sticky-header);background:var(--midnight);color:var(--ivory);text-align:center;font-family:'Jost',sans-serif;font-weight:500;text-transform:uppercase;letter-spacing:.18em;font-size:0.75rem;padding:1rem;border-top:1px solid rgba(var(--gold-soft-rgb),.4)}

/* =================================================================
   RESPONSIVE
   ================================================================= */
@media (max-width:900px){
  .grid--4{grid-template-columns:repeat(2,1fr)}
  .why{grid-template-columns:1fr;gap:3rem;justify-items:center;text-align:center}
  .why__content .section__title::after{margin-left:auto;margin-right:auto}
  .contact{grid-template-columns:1fr}
  .section{padding:6rem 2rem}
  /* Hamburger from tablet down. The inline links are hidden entirely and replaced
     by the full-screen .mnav overlay — no partial/clipped dropdown. */
  .nav__links{display:none}
  .nav.scrolled,.nav{background:rgba(var(--midnight-rgb),.92);backdrop-filter:blur(10px)}
  .nav__toggle{display:block}
}
/* ---------------------------------------------------------------------------
   HEADER — GAPS ARE STRUCTURAL, COLLAPSE IS MEASURED.

   This replaces four hand-tuned width bands. Those bands encoded, in pixels,
   how wide the nav *happened* to be with Jost at 16px root and Chrome's metrics.
   Every one of those assumptions is a user setting: bump the browser's default
   font size, zoom to 110%, or load with the webfont still swapping and the real
   content width moves while the breakpoints do not. That is how a header that
   passes at 1300 crowds at 1300 on somebody else's machine.

   So the pixel geometry is no longer expressed as breakpoints. It is expressed
   as MINIMUM SPACING that cannot be squeezed:
       32px  wordmark -> nav          .nav__links margin-left
       22px  between nav items        .nav__links gap        (floor is 16)
       22px  last item -> pill        same flex gap
       16px  nav -> phone/MORE        .nav__tel / .nav__toggle margin-left
       28px  viewport edge            .nav__inner padding
   Nothing tightens these. When the content no longer fits, items COLLAPSE into
   the MORE menu instead — which is the rule Tony set: collapsing early beats
   crowding, always. Deciding *when* needs the rendered width, which only the
   browser knows, so script.js measures it (see fitNav) and sets the classes
   below. The wordmark is never part of that negotiation: nav flexes, brand does
   not.

   Enforced at every width from 375 to 1920 in 50px steps by
   build/audit_header.py — as computed geometry, not screenshots. A header that
   is crowded but not overflowing fails that gate.
--------------------------------------------------------------------------- */
@media (min-width:901px){
  /* The header gets more room than the 1200px content column. Nothing else on
     the page moves; only .nav__inner widens. */
  .nav__inner{max-width:1340px;padding-left:1.75rem;padding-right:1.75rem}
  .nav__links{margin-left:32px;gap:22px}
  .nav__links a{letter-spacing:.09em}
  .nav__tel{margin-left:16px}
  /* The phone number is the first thing to go — it is a duplicate of the icon,
     which stays tappable. fitNav adds this before it hides any destination. */
  .nav--tight .nav__telNum{display:none}
  .nav--tight .nav__tel{width:38px;height:38px;justify-content:center;
    border:1px solid rgba(var(--gold-soft-rgb),.38);border-radius:50%}
  /* Collapse: fitNav marks links itself, in priority order, because the hrefs
     differ page to page and the labels do not. Each step only ever REMOVES an
     item from the bar; every destination stays reachable in the MORE overlay,
     which already carries the full list. */
  .nav--auto .nav__links a.nav__drop{display:none}
  /* MORE appears the moment anything is hidden, and says so — a bare hamburger
     beside visible links reads as a duplicate rather than as "there is more". */
  .nav--more .nav__toggle{display:inline-flex;align-items:center;gap:.4rem;
    margin-left:16px;color:var(--ivory);opacity:.82;font-family:'Jost',sans-serif;
    font-weight:300;text-transform:uppercase;letter-spacing:.1em;font-size:.68rem;
    line-height:1;white-space:nowrap;flex:none}
  .nav--more .nav__toggle::after{content:"More"}
  .nav--more .nav__toggle svg{width:20px;height:20px}
  .nav--more .nav__toggle:hover{opacity:1;color:var(--gold-soft)}
  body.mnav-open .nav__tel{display:none}   /* never competes with the open menu */
  /* NO-JS FALLBACK. fitNav sets .nav--auto as soon as it runs; without it the
     old conservative band still applies, so a scripting failure degrades to a
     slightly sparse header rather than a crowded one. */
  .nav:not(.nav--auto) .nav__links a[href="#why"],
  .nav:not(.nav--auto) .nav__links a[href="/#why"]{display:none}
  .nav:not(.nav--auto) .nav__telNum{display:none}
}
@media (min-width:901px) and (max-width:1199px){
  .nav:not(.nav--auto) .nav__links a[href="/homes.html"]{display:none}
  .nav:not(.nav--auto) .nav__toggle{display:inline-flex;align-items:center;
    gap:.4rem;margin-left:16px;color:var(--ivory);opacity:.82;
    font-family:'Jost',sans-serif;font-weight:300;text-transform:uppercase;
    letter-spacing:.1em;font-size:.68rem;line-height:1;white-space:nowrap}
  .nav:not(.nav--auto) .nav__toggle::after{content:"More"}
  .nav:not(.nav--auto) .nav__toggle svg{width:20px;height:20px}
}
@media (max-width:640px){
  .nav__links{display:none}
  .nav.scrolled,.nav{background:rgba(var(--midnight-rgb),.92);backdrop-filter:blur(10px)}
  .nav__toggle{display:block}
  .grid--3,.grid--4{grid-template-columns:1fr}
  .section{padding:4rem 1.5rem}
  .hero{min-height:90svh}
  .why__photo{width:240px}
  body{padding-bottom:56px}
  .mobile-callbar{display:block}
}
@media (min-width:641px) and (max-width:900px){
  .grid--3{grid-template-columns:repeat(2,1fr)}
}

/* Lightbox (unchanged behaviour, refined chrome) */
.lightbox{position:fixed;inset:0;z-index:var(--z-modal);background:rgba(var(--midnight-rgb),.94);display:none;align-items:center;justify-content:center;padding:1.5rem}
.lightbox.open{display:flex}
.lightbox__video{width:min(960px,100%);max-height:86dvh;border-radius:var(--radius);background:var(--video-bg);box-shadow:0 30px 80px rgba(var(--black-rgb),.6)}
.lightbox__close{position:absolute;top:1.2rem;right:1.5rem;background:none;border:none;color:var(--ivory);font-size:2rem;line-height:1;cursor:pointer;padding:0.25rem 0.5rem}
.lightbox__close:hover{color:var(--gold)}

/* Subtle scroll-in reveal. Fires once. `--i` is the stagger index within a
   group, set by script.js; 70ms apart reads as a wave, not a queue. */
@media (prefers-reduced-motion:no-preference){
  .reveal{opacity:0;transform:translateY(18px);
    transition:opacity var(--dur-3) var(--ease),transform var(--dur-3) var(--ease);
    transition-delay:calc(var(--i,0) * 70ms)}
  .reveal.in{opacity:1;transform:none}
}

/* =================================================================
   SUBPAGES — community detail, floor-plan library, partners
   ================================================================= */
.page-hero{position:relative;min-height:58svh;display:flex;align-items:flex-end;color:var(--ivory);overflow:hidden;margin-top:-74px;padding-top:74px}
.page-hero__img{position:absolute;inset:0;z-index:var(--z-local-behind)}
.page-hero__img img{width:100%;height:100%;object-fit:cover}
.page-hero__overlay{position:absolute;inset:0;z-index:var(--z-local-under);background:linear-gradient(180deg,rgba(var(--midnight-deep-rgb),.30) 0%,rgba(var(--midnight-deep-rgb),.55) 55%,rgba(var(--midnight-deep-rgb),.86) 100%)}
/* NARROW-VIEWPORT SCRIM. At 375px the hero title sits lower in the frame — the
   partners stat tiles are two-line and taller than the inline text they
   replaced — which moved the title over a brighter band of the photograph and
   dropped /partners page-hero__title from 7.47 to 6.08. Deepened here rather
   than re-baselined: 6.08 still clears the 3.0 floor, but the baseline exists
   to catch exactly this kind of silent drift. Deepening also darkens what sits
   behind the stat tiles, whose own rgba(0,0,0,.20) fill needs the help. */
@media(max-width:767px){
  .page-hero__overlay{background:linear-gradient(180deg,
    rgba(var(--midnight-deep-rgb),.46) 0%,
    rgba(var(--midnight-deep-rgb),.66) 55%,
    rgba(var(--midnight-deep-rgb),.90) 100%)}
}
/* The horse-country hero is 1.74:1 but the band it sits in runs from ~1:1 at
   375px to ~3.6:1 at 1440px. Holding the crop just above centre keeps the oak
   line and the board fence in frame at every width instead of landing on bare
   grass at desktop. */
.page-hero__img img{object-position:center 38%}
/* Attribution on a section photo (CC BY 2.0 requires it wherever the photo runs).
   Sits inside .dsc__media, which is position:relative, so it rides the image. */
.dsc__credit{position:absolute;right:.5rem;bottom:.4rem;z-index:var(--z-local-over);margin:0;
  font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.04em;
  color:rgba(255,255,255,.72);text-shadow:0 1px 3px rgba(0,0,0,.6)}
.dsc__credit a{color:inherit;text-decoration:underline;text-underline-offset:2px}
.dsc__credit a:hover{color:var(--ivory)}
.page-hero__credit{position:absolute;right:1rem;bottom:.5rem;z-index:var(--z-local-raise);margin:0;
  font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.08em;color:rgba(var(--ivory-rgb),.62)}
.page-hero__credit a{color:inherit;text-decoration:underline;text-underline-offset:2px}
.page-hero__credit a:hover{color:var(--ivory)}
@media (max-width:640px){.page-hero__credit{right:.7rem;font-size:0.625rem}}
.page-hero__inner{max-width:var(--max);margin:0 auto;width:100%;padding:0 2rem 4rem;position:relative}
/* TEXT-PROTECTION SCRIM — behind the copy ONLY, not the hero.
   The hero copy sits ~30-55% down the hero, inside the overlay's weakest band
   (.30), so ivory eyebrows measured 3.3-4.4 against a 4.5 need on the brighter
   community photos. This is NOT a global scrim: it is a soft plume anchored to
   the text column that fades to nothing well before the hero edges, so the
   photograph is untouched everywhere except immediately behind the words.
   Left-anchored to follow the left-set copy; every hero is still measured by
   the contrast gate at 375 and 1440. */
.page-hero__inner::before{content:"";position:absolute;z-index:var(--z-local-under);
  left:-8%;right:20%;top:-6%;bottom:-4%;pointer-events:none;
  background:radial-gradient(120% 90% at 22% 50%,
    rgba(var(--midnight-deep-rgb),.62) 0%,
    rgba(var(--midnight-deep-rgb),.42) 42%,
    rgba(var(--midnight-deep-rgb),0) 75%)}
@media (max-width:640px){
  .page-hero__inner::before{left:-12%;right:-6%;
    background:radial-gradient(150% 80% at 40% 55%,
      rgba(var(--midnight-deep-rgb),.66) 0%,
      rgba(var(--midnight-deep-rgb),.44) 46%,
      rgba(var(--midnight-deep-rgb),0) 80%)}
}
.page-hero__eyebrow{display:block;margin-bottom:1rem;color:var(--gold-soft)}
/* IVORY EYEBROWS ON PHOTO HEROES.
   Champagne #cbb489 cannot reach AA 4.5:1 over a bright hero photo (measured
   1.90-3.91). Ivory does, and it keeps the imagery — no global scrim bump.
   Champagne is retained ONLY on the placeholder-gradient heroes (.--ph), which
   are solid dark and where it already passes. Scoped with :has() so the rule
   follows the hero's actual backdrop, not a hand-maintained page list. Every
   one of the 17 heroes is still measured per-side by the contrast gate — this
   is the fix, the gate is the proof. */
.page-hero:not(:has(.page-hero__img--ph)) .page-hero__eyebrow,
.page-hero:not(:has(.page-hero__img--ph)) .crumb,
.page-hero:not(:has(.page-hero__img--ph)) .crumb a{color:var(--ivory)}
.page-hero__title{font-size:clamp(2.4rem,5.2vw,3.7rem);font-weight:500;color:var(--ivory);line-height:1.05;text-wrap:balance}
.page-hero__rule{display:block;width:56px;height:1px;background:var(--gold-soft);margin:1.5rem 0}
.page-hero__blurb{max-width:62ch;font-family:'Jost',sans-serif;font-weight:300;color:rgba(var(--ivory-rgb),.9);font-size:clamp(1rem,1.4vw,1.12rem)}
.crumb{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.2em;font-size:0.75rem;color:var(--gold-soft);margin-bottom:1.5rem;display:inline-block}
.crumb a{color:var(--gold-soft)}
.crumb a:hover{color:var(--ivory)}

/* count line under the section head */
.section__count{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.2em;font-size:0.75rem;color:var(--gold);margin-top:1rem}

/* home cards without an interior photo — elegant text-forward variant */
.home--txt{display:flex;flex-direction:column;justify-content:space-between}
.home--txt .home__body{padding:2rem 2rem 2rem}
.home__plan{font-family:'Cormorant Garamond',serif;font-size:1.5rem;font-weight:600;color:var(--midnight);margin-top:0.25rem}
.home__badge-row{display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem}
.home__badge{display:inline-block;font-family:'Jost',sans-serif;font-weight:400;font-size:0.625rem;padding:0.25rem 0.75rem;border:1px solid var(--line);border-radius:var(--radius);text-transform:uppercase;letter-spacing:.18em;color:var(--midnight)}
.home__badge--uc{color:var(--gold);border-color:rgba(var(--gold-rgb),.5)}
.home__badge--mir{color:var(--verified);border-color:rgba(var(--verified-rgb),.4)}
.home__eta{font-size:0.75rem;text-transform:uppercase;letter-spacing:.12em;color:var(--muted)}
.home--txt .home__media .home__badge{position:absolute;top:1rem;right:1rem;background:rgba(var(--midnight-rgb),.72);backdrop-filter:blur(4px);color:var(--ivory);border-color:rgba(var(--gold-soft-rgb),.4)}

/* coming-soon empty state */
.emptystate{text-align:center;max-width:560px;margin:0 auto;padding:3rem 0 1rem}
.emptystate h3{font-size:2rem;font-weight:600;margin-bottom:1rem}
.emptystate p{color:var(--muted);margin-bottom:2rem}

/* contact CTA band at the bottom of subpages */
.cta-band{background:var(--midnight);color:var(--ivory);text-align:center;padding:6rem 2rem}
.cta-band__eyebrow{display:block;margin-bottom:1rem;color:var(--gold-soft)}
.cta-band h2{color:var(--ivory);font-size:clamp(2rem,4vw,2.8rem);font-weight:500}
.cta-band__rule{display:block;width:54px;height:1px;background:var(--gold);margin:1.5rem auto 2rem}
.cta-band__btns{display:flex;gap:1rem;justify-content:center;flex-wrap:wrap;margin-top:0.5rem}

/* floor-plan library cards */
.plan__price-row{display:flex;align-items:baseline;justify-content:space-between;gap:0.5rem;margin-top:0.25rem}
.plan__from{font-family:'Cormorant Garamond',serif;color:var(--midnight);font-weight:600;font-size:1.5rem}
.plan__from span{color:var(--gold);font-size:0.75rem;font-family:'Jost',sans-serif;font-weight:400;letter-spacing:.05em}
.plan__stories{font-size:0.75rem;text-transform:uppercase;letter-spacing:.12em;color:var(--muted)}
/* margin-bottom:auto eats the leftover column space, which pins .plan__actions
   to the foot of every card while leaving its own 1rem gap intact. */
.plan__where{margin-top:1rem;margin-bottom:auto;padding-top:1rem;border-top:1px solid var(--line);font-size:0.875rem;color:var(--muted);font-weight:300;line-height:1.7}
/* always-visible realtor actions on a floor-plan card */
.plan__actions{display:flex;flex-wrap:wrap;gap:0.5rem;margin-top:1rem;padding-top:1rem;border-top:1px solid var(--line)}
.plan__act{display:inline-flex;align-items:center;gap:0.5rem;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.13em;font-size:0.75rem;font-weight:500;border-radius:var(--radius);padding:0.5rem 0.75rem;cursor:pointer;transition:border-color var(--dur-2) var(--ease),color var(--dur-2) var(--ease),background var(--dur-2) var(--ease)}
.plan__act svg{width:14px;height:14px;flex:none}
.plan__act--dl{background:var(--midnight);color:var(--ivory);border:1px solid var(--midnight)}
.plan__act--dl:hover{background:var(--gold);border-color:var(--gold);color:var(--midnight)}
.plan__act--req{background:none;color:var(--muted);border:1px dashed var(--line)}
.plan__act--req:hover{border-color:var(--gold);color:var(--gold)}
.plan__act--vid{background:none;color:var(--midnight);border:1px solid var(--line)}
.plan__act--vid:hover{border-color:var(--gold);color:var(--gold)}
/* floor-plan library: download-all-brochures toolbar */
.fp-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:0.5rem 1rem;margin-bottom:1.5rem;padding:1rem 1rem;background:var(--midnight);border-radius:var(--radius)}
.fp-dlall{display:inline-flex;align-items:center;gap:0.5rem;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;font-weight:600;color:var(--midnight);background:var(--gold);border-radius:var(--radius);padding:0.75rem 1rem;transition:background var(--dur-2) var(--ease)}
.fp-dlall svg{width:16px;height:16px}
.fp-dlall:hover{background:var(--gold-soft)}
.fp-dlall__meta{font-weight:400;letter-spacing:.1em;opacity:.72}
.fp-toolbar__note{margin:0;color:var(--ivory);opacity:.82;font-size:0.875rem;font-weight:300;line-height:1.5}
/* Per-community HOA inside the "Offered in" list. A plan spans communities with
   different dues, so the figure sits next to the community it belongs to and
   the plan never carries one of its own. */
.plan__hoa{font-family:'Jost',sans-serif;font-size:.68rem;letter-spacing:.04em;
  color:var(--gold);white-space:nowrap}
.plan__where b{display:block;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.16em;font-size:0.625rem;color:var(--gold);font-weight:500;margin-bottom:0.5rem}
.plan__where a{color:var(--ink);border-bottom:1px solid var(--line);transition:border-color var(--dur-2) var(--ease),color var(--dur-2) var(--ease)}
.plan__where a:hover{color:var(--gold);border-color:var(--gold)}
.plan__wmore{display:inline;margin-left:0.25rem;background:none;border:0;padding:0;cursor:pointer;font:inherit;color:var(--gold);border-bottom:1px solid var(--gold);line-height:inherit}
.plan__wmore:hover{color:var(--ink);border-color:var(--ink)}
.plan__media--still{cursor:default}

/* section intro paragraph + "view all" link */
.viewall{text-align:center;margin-top:3rem}

/* ---------- Partners page ---------- */
.partner-intro{max-width:760px}
.partner-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:1.5rem}
.resource{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);padding:1.5rem 1.5rem;box-shadow:var(--shadow);display:flex;flex-direction:column;gap:0.75rem}
.resource h3{font-size:1.25rem;font-weight:600}
.resource__meta{font-size:0.875rem;color:var(--muted);text-transform:uppercase;letter-spacing:.12em}
.resource__links{display:flex;flex-wrap:wrap;gap:0.5rem;margin-top:0.5rem}
.chip{display:inline-flex;align-items:center;gap:0.5rem;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;font-weight:500;padding:0.5rem 1rem;border:1px solid var(--midnight);border-radius:var(--radius);color:var(--midnight);transition:background var(--dur-2) var(--ease),color var(--dur-2) var(--ease)}
.chip:hover{background:var(--midnight);color:var(--ivory)}
.chip--muted{border-color:var(--line);color:var(--muted);cursor:default;pointer-events:none}
.chip--muted:hover{background:transparent;color:var(--muted)}
.chip svg{width:13px;height:13px}

/* =============================================================================
   MOBILE MENU — full-screen overlay (replaces the old clipped dropdown).
   Desktop never sees it; from 900px down it's the only menu.
   ========================================================================== */
.mnav{display:none}
@media (max-width:900px){
  .mnav{display:flex;position:fixed;inset:0;z-index:var(--z-modal);background:var(--midnight);
    flex-direction:column;justify-content:center;padding:5.5rem 1.75rem 2.5rem;
    overflow-y:auto;-webkit-overflow-scrolling:touch;
    opacity:0;visibility:hidden;transform:translateY(-10px);
    transition:opacity var(--dur-2) var(--ease),transform var(--dur-2) var(--ease),visibility var(--dur-2)}
  .mnav.is-open{opacity:1;visibility:visible;transform:none}
  .mnav__close{position:absolute;top:.9rem;right:1rem;width:48px;height:48px;
    display:flex;align-items:center;justify-content:center;background:none;border:none;
    color:var(--ivory);font-size:2.1rem;line-height:1;cursor:pointer;opacity:.85}
  .mnav__close:active{opacity:1;color:var(--gold-soft)}
  .mnav__list{display:flex;flex-direction:column}
  .mnav__list a{display:flex;align-items:center;min-height:48px;padding:.5rem 0;
    font-family:'Cormorant Garamond',serif;font-size:1.95rem;font-weight:500;
    line-height:1.15;color:var(--ivory);letter-spacing:.01em}
  .mnav__list a:active{color:var(--gold-soft)}
  /* agents' entrance — gold, set apart by a thin rule */
  .mnav__list a.mnav__partner{color:var(--gold-soft);margin-top:.9rem;padding-top:1.3rem;
    border-top:1px solid rgba(var(--gold-soft-rgb),.32);
    flex-direction:column;align-items:flex-start;gap:.1rem}
  .mnav__tag{font-family:'Jost',sans-serif;font-size:.58rem;font-weight:500;line-height:1;
    letter-spacing:.2em;text-transform:uppercase;color:rgba(var(--gold-soft-rgb),.72)}
  body.mnav-open{overflow:hidden}
  /* nothing floats over the menu */
  body.mnav-open .tgchat-launch,
  body.mnav-open .tgchat-panel,
  body.mnav-open .mobile-callbar,
  body.mnav-open .pbar{display:none!important}
}
@media (max-width:380px){
  .mnav__list a{font-size:1.7rem;min-height:46px}
  .mnav{padding:5rem 1.4rem 2rem}
}

/* =============================================================================
   RED TAG EVENT EXPIRY — single source of truth is build/config.py REDTAG_END_DATE.
   An inline <head> script stamps .redtag-off on <html> once the ET date passes the
   end date, retiring every Red Tag badge / legend / filter / label site-wide with
   NO redeploy. Prices are untouched — they always come from inventory data.
   ========================================================================== */
.redtag-off .card__tag--rt,
.redtag-off .badge--redtag,
.redtag-off .plan__rt,
.redtag-off .rt-toggle,
.redtag-off .rt-ui,
.redtag-off .cm-card__rt{display:none!important}
.redtag-off .cm-pin--rt .cm-pin__dot{box-shadow:0 3px 10px rgba(var(--midnight-rgb),.5)}

/* =============================================================================
   CURRENT PROGRAMS (/partners only — the only place rates/APRs appear).
   Deliberately NOT a reproduction of the navy/red builder flyers: same quiet
   midnight/ivory/champagne language as the rest of the site.
   ========================================================================== */
.prog-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:1.5rem;align-items:stretch}
.prog{display:flex;flex-direction:column;background:var(--white);border:1px solid var(--line);
  border-radius:var(--radius);border-top:2px solid var(--gold);padding:2rem 1.5rem 1.5rem;
  box-shadow:var(--shadow);height:100%}
.prog--lead{background:linear-gradient(180deg,rgba(var(--gold-soft-rgb),.12),rgba(var(--gold-soft-rgb),0) 46%),var(--white);
  border-top-width:3px}
/* header: name + deadline badge (the ONLY place a date appears) */
.prog__top{display:flex;align-items:flex-start;justify-content:space-between;gap:0.75rem;min-height:2.4rem}
.prog__name{font-family:'Jost',sans-serif;font-size:0.75rem;font-weight:500;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);margin:0;line-height:1.4}
.prog__badge{flex:none;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.1em;
  font-size:0.625rem;font-weight:600;color:var(--midnight);background:var(--gold-soft);
  border-radius:2px;padding:0.25rem 0.5rem;line-height:1.2;max-width:52%;text-align:right}
.prog__badge--quiet{background:none;color:var(--muted);border:1px solid var(--line)}
/* the one number that carries the card */
.prog__hero-wrap{margin-top:1rem}
.prog__hero{font-family:'Cormorant Garamond',serif;font-size:clamp(2.4rem,4.8vw,3.75rem);font-weight:600;line-height:.95;
  color:var(--midnight);margin:0;letter-spacing:-.01em}
.prog__apr{font-family:'Jost',sans-serif;font-size:0.75rem;font-weight:500;letter-spacing:.1em;
  color:var(--gold);margin:0.25rem 0 0}
.prog__support{font-family:'Jost',sans-serif;font-size:0.75rem;font-weight:300;line-height:1.55;
  color:var(--muted);margin:0.75rem 0 0;max-width:24ch}
/* commission ladder: three steps, small -> large */
.prog__ladder{display:flex;align-items:flex-end;gap:0.5rem;margin-top:1rem}
.prog__step{flex:1;background:var(--cream);border-radius:var(--radius);padding:0.5rem 0.25rem;text-align:center}
.prog__step b{display:block;font-family:'Cormorant Garamond',serif;font-weight:600;color:var(--midnight);line-height:1}
.prog__step span{display:block;font-size:0.625rem;color:var(--muted);margin-top:0.25rem;line-height:1.25}
.prog__step--s b{font-size:1.25rem}
.prog__step--m b{font-size:1.5rem}
.prog__step--l b{font-size:2rem}
.prog__step--l{background:rgba(var(--gold-soft-rgb),.22)}
/* actions pinned to the bottom so every card lines up */
.prog__actions{margin-top:auto;padding-top:1.5rem}
.prog__dl{display:inline-flex;align-items:center;gap:0.5rem;font-family:'Jost',sans-serif;text-transform:uppercase;
  letter-spacing:.12em;font-size:0.75rem;font-weight:500;color:var(--ivory);background:var(--midnight);
  border:1px solid var(--midnight);border-radius:var(--radius);padding:0.5rem 1rem;cursor:pointer;
  transition:background var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease),color var(--dur-2) var(--ease)}
.prog__dl svg{width:14px;height:14px;flex:none}
.prog__dl:hover{background:var(--gold);border-color:var(--gold);color:var(--midnight)}
/* every word of legal text lives in here */
.prog__terms{border-top:1px solid var(--line);margin-top:1rem;padding-top:0.75rem}
.prog__terms summary{cursor:pointer;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.13em;
  font-size:0.75rem;font-weight:500;color:var(--gold);list-style:none}
.prog__terms summary::-webkit-details-marker{display:none}
.prog__terms summary::after{content:" +";color:var(--muted)}
.prog__terms[open] summary::after{content:" –"}
.prog__terms p{margin-top:0.75rem;font-size:0.75rem;line-height:1.65;color:var(--muted);font-weight:300;
  max-height:240px;overflow-y:auto}
.prog__detail{color:var(--ink);font-size:0.75rem;max-height:none}
.prog-foot{display:flex;align-items:center;gap:1rem;margin-top:2rem;padding-top:1rem;border-top:1px solid var(--line)}
.prog-eho{width:34px;height:34px;flex:none;color:var(--midnight)}
.prog-foot p{font-size:0.75rem;color:var(--muted);font-weight:300;line-height:1.6;margin:0}
@media (max-width:560px){
  .prog-grid{grid-template-columns:1fr;gap:1rem}
  .prog{padding:1.5rem 1.5rem 1rem}
  .prog__hero{font-size:clamp(2.4rem,4.8vw,3.75rem)}
  .prog__support{max-width:none}
}

/* partners hero strip */
/* ---- PARTNER HERO STRIP — six interactive elements, one uniform row -------
   All six are real <a href>. The four stats were <span>s, which meant they were
   not keyboard reachable, showed no destination on hover, and sat on a
   different baseline from the two buttons.

   UNIFORMITY IS ENFORCED BY THE SHARED .partner-strip__el CLASS, which owns
   every property that must match across all six — height, vertical alignment,
   radius, transition, focus ring, tap target. A variant class may only change
   colour and fill. build/audit_partners_hero.py asserts identical computed
   height on all six at build time, so a divergence fails the build rather than
   shipping as a ragged row. */
.partner-strip{display:flex;flex-wrap:wrap;align-items:stretch;gap:.7rem;margin-top:1.8rem}
.partner-strip__el{
  /* the uniform contract — do not override these in a variant */
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  min-height:44px;                      /* tap target floor, all six */
  padding:.62rem 1.15rem;
  border:1px solid transparent;         /* every variant reserves the same 1px */
  border-radius:var(--radius);
  font-family:'Jost',sans-serif;
  text-align:center;
  transition:background 180ms var(--ease),border-color 180ms var(--ease),
             transform 180ms var(--ease);
}
.partner-strip__el:hover{transform:translateY(-2px)}
.partner-strip__el:focus-visible{outline:2px solid var(--gold-soft);outline-offset:3px}
.partner-strip__cta{text-transform:uppercase;letter-spacing:.14em;font-size:.7rem;font-weight:500;color:var(--midnight);background:var(--gold-soft);border-color:var(--gold-soft)}
.partner-strip__cta:hover{background:var(--gold);border-color:rgba(var(--gold-soft-rgb),.7)}
.partner-strip__vcf{text-transform:uppercase;letter-spacing:.14em;font-size:.68rem;font-weight:500;color:var(--gold-soft);border-color:rgba(var(--gold-soft-rgb),.5)}
.partner-strip__vcf:hover{background:rgba(var(--gold-soft-rgb),.14);border-color:rgba(var(--gold-soft-rgb),.7)}
/* stat tiles: equal width, so four of them read as one set rather than four
   different-length labels */
.partner-strip__stat{flex:1 1 0;min-width:8.5rem;
  border-color:rgba(var(--gold-soft-rgb),.30);
  background:rgba(0,0,0,.20);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}
.partner-strip__stat:hover{border-color:rgba(var(--gold-soft-rgb),.70);background:rgba(0,0,0,.28)}
.partner-strip__stat b{font-family:'Cormorant Garamond',Georgia,serif;font-size:1.35rem;
  line-height:1;color:var(--gold-soft);font-weight:500}
.partner-strip__stat span{text-transform:uppercase;letter-spacing:.12em;font-size:.6rem;
  font-weight:500;color:rgba(var(--ivory-rgb),.80);margin-top:.22rem}
/* MOBILE: two buttons full width stacked, four stats in a 2x2 grid. Identical
   styling and tap targets — the row reflows, the treatment does not change. */
@media(max-width:767px){
  .partner-strip{display:grid;grid-template-columns:1fr 1fr;gap:.6rem}
  .partner-strip__cta,.partner-strip__vcf{grid-column:1 / -1}
  .partner-strip__stat{min-width:0}
  /* Uniform height across all six. The two buttons are single-line (44px) and
     the stat tiles are two-line (number + label, 63px), so without this the row
     ships ragged. min-height, not height: a label that ever wraps grows the
     tile rather than clipping, and audit_partners_hero.py --render catches the
     resulting inequality. */
  .partner-strip__el{min-height:64px}
}
/* agent toolkit grid — auto-fit so 5 cards sit evenly and wrap cleanly */
.toolkit{display:grid;grid-template-columns:repeat(auto-fit,minmax(212px,1fr));gap:1.5rem;margin-top:0.5rem}
/* community flyer grid */
.flyer-actions{display:flex;justify-content:center;margin-bottom:1.5rem}
.flyer-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:0.75rem}
.flyer{display:flex;align-items:center;justify-content:space-between;gap:0.75rem;min-height:52px;padding:0.75rem 1rem;background:var(--white);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);transition:border-color var(--dur-2) var(--ease),transform var(--dur-2) var(--ease)}
.flyer:hover{border-color:var(--gold);transform:translateY(-2px)}
.flyer__name{font-size:1rem;color:var(--ink);font-weight:400}
.flyer__dl{font-family:'Jost',sans-serif;font-size:0.75rem;font-weight:600;letter-spacing:.14em;color:var(--ivory);background:var(--midnight);border-radius:2px;padding:0.25rem 0.5rem;flex:none}
.flyer:hover .flyer__dl{background:var(--gold);color:var(--midnight)}
/* video walkthrough request */
.vidreq{max-width:760px;margin:0 auto;text-align:center}
.vidreq__copy{font-family:'Cormorant Garamond',serif;font-size:1.5rem;color:var(--midnight);line-height:1.4;margin-bottom:1.5rem}
.vidreq__actions{display:flex;flex-wrap:wrap;gap:0.75rem;justify-content:center}
.joinlist{margin-top:2rem;text-align:center}
.joinlist a{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;color:var(--gold);border-bottom:1px solid var(--gold);padding-bottom:0.25rem}
/* partners sticky action bar (mobile) — replaces the generic call bar here */
.pbar{display:none}
@media (max-width:640px){
  .pbar{display:grid;grid-template-columns:repeat(3,1fr);position:fixed;left:0;right:0;bottom:0;z-index:var(--z-sticky-header);
    background:var(--midnight);border-top:1px solid rgba(var(--gold-soft-rgb),.25);box-shadow:0 -8px 24px rgba(var(--black-rgb),.28)}
  .pbar__btn{display:flex;align-items:center;justify-content:center;min-height:56px;font-family:'Jost',sans-serif;
    text-transform:uppercase;letter-spacing:.12em;font-size:0.75rem;font-weight:500;color:var(--ivory)}
  .pbar__btn:active{background:rgba(var(--white-rgb),.07)}
  .pbar__btn--gold{color:var(--midnight);background:var(--gold-soft)}
  body.partners .mobile-callbar{display:none}   /* one sticky bar only */
  body.partners{padding-bottom:56px}
}
.tk{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);padding:1.5rem 1.5rem 1.5rem;box-shadow:var(--shadow);display:flex;flex-direction:column;gap:0.5rem;transition:transform var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease)}
.tk:hover{transform:translateY(-3px);box-shadow:0 18px 44px rgba(var(--midnight-rgb),.14);border-color:var(--gold-soft)}
.tk__ico{width:30px;height:30px;color:var(--gold);margin-bottom:0.25rem}
.tk h3{font-size:1.25rem;font-weight:600}
.tk p{font-size:0.875rem;color:var(--muted);font-weight:300;line-height:1.6;flex:1}
/* CTA block pins to the card's bottom edge, so every card's buttons sit on one
   shared baseline no matter how long its heading or paragraph runs. `flex:1` on
   .tk p alone did NOT do this — measured 2026-07-22, row 1 at 1440px had four
   equal-height (365px) cards whose CTA blocks started at 1471/1404/1451/1471.
   margin-top:auto is the only thing that actually bottom-pins the block; the
   padding-top keeps the old 1rem of breathing room above it. */
.tk__links{display:flex;flex-direction:column;gap:0.5rem;margin-top:auto;padding-top:1rem}
/* Uniform height is what actually puts the primary CTAs on one baseline. The
   toolkit columns are ~219px at 768px, so "Browse 26 communities" (187px of text)
   and "Request a walkthrough" (191px) CANNOT fit on one line there — they wrap to
   two while "Open the maps" stays at one, and the buttons land 20px apart. No
   amount of bottom-pinning fixes that; only equal box heights do. 3.6875rem is
   the natural two-line height at this type size, so a wrapped label fills it and
   a short label matches it. Bonus: 59px clears the 44px touch-target minimum. */
.tk__link{display:inline-flex;align-items:center;justify-content:center;text-align:center;min-height:3.6875rem;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.13em;font-size:0.75rem;font-weight:500;padding:0.5rem 1rem;border-radius:var(--radius);border:1px solid var(--line);color:var(--midnight);transition:border-color var(--dur-2) var(--ease),color var(--dur-2) var(--ease),background var(--dur-2) var(--ease)}
.tk__link--solid{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}
.tk__link--solid:hover{background:var(--gold);border-color:var(--gold);color:var(--midnight)}
.tk__link:not(.tk__link--solid):hover{border-color:var(--gold);color:var(--gold)}
/* co-op steps */
.coop{margin-top:0.5rem}
.coop__step{padding:1.5rem 0}
.coop__n{font-family:'Cormorant Garamond',serif;font-size:2rem;color:var(--gold);font-weight:600;line-height:1;display:block;margin-bottom:0.5rem}
.coop__step h3{font-size:1.25rem;font-weight:600;margin-bottom:0.5rem}
.coop__step p{font-size:0.875rem;color:var(--muted);font-weight:300;line-height:1.65}
.coop__note{margin-top:1.5rem;color:var(--muted);font-size:0.875rem}
.coop__note a{color:var(--midnight);border-bottom:1px solid var(--gold);font-weight:400}
/* agent signup form */
.partner-form{max-width:680px;margin:0 auto}
.partner-form__row{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem}
.partner-form .opt{text-transform:none;letter-spacing:0;color:var(--muted);font-size:.8em}
@media (max-width:560px){.partner-form__row{grid-template-columns:1fr}}

/* footer partners link (small, quiet) */
.footer__partners{margin-top:1rem;font-size:0.75rem}
.footer__partners a{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.16em;color:rgba(var(--ivory-rgb),.5)}
.footer__partners a:hover{color:var(--gold-soft)}

@media (max-width:640px){
  .page-hero{min-height:52svh}
  .page-hero__inner{padding:0 1.5rem 2rem}
  .cta-band{padding:4rem 1.5rem}
}

/* =================================================================
   INTERACTIVE COMMUNITY MAP (Leaflet)
   ================================================================= */
.community-map{height:480px;width:100%;border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);background:var(--map-surface);z-index:var(--z-local-raise)}
/* STACKING: Leaflet builds internal panes at z-index 400-800. The sticky nav
   was at 50, so map tiles rendered OVER the header while scrolling. Two
   defences: the map gets its own stacking context so those 400s can never
   escape it, and the nav is lifted above anything Leaflet creates. */
.leaflet-container{font-family:'Jost',sans-serif;background:var(--map-surface);position:relative;z-index:var(--z-local-base);isolation:isolate}
.mappage,.spotmap,.am-wrap{position:relative;z-index:var(--z-local-base);isolation:isolate}
/* refined pin: midnight dot, gold ring */
/* clustered pins (luxury) — overlapping communities group into a count */
.cm-cluster{background:none;border:0}
.cm-cluster span{display:flex;align-items:center;justify-content:center;width:38px;height:38px;margin:2px;
  border-radius:50%;background:var(--midnight);color:var(--gold-soft);border:2px solid var(--gold);
  font-family:'Jost',sans-serif;font-size:0.875rem;font-weight:500;box-shadow:0 4px 12px rgba(var(--midnight-rgb),.5)}
.marker-cluster-small,.marker-cluster-medium,.marker-cluster-large{background:none}
.cm-pin{background:none;border:0;display:flex;align-items:center;justify-content:center}
.cm-pin__dot{display:block;width:20px;height:20px;border-radius:50%;background:var(--midnight);border:2.5px solid var(--gold);box-shadow:0 3px 10px rgba(var(--midnight-rgb),.5);transition:transform var(--dur-1) var(--ease)}
.cm-pin:hover .cm-pin__dot,.cm-pin:focus .cm-pin__dot{transform:scale(1.3)}
/* instant name label on hover/tap */
.cm-tip.leaflet-tooltip{background:var(--midnight);color:var(--ivory);border:1px solid var(--gold-soft);border-radius:var(--radius);box-shadow:0 6px 18px rgba(var(--midnight-rgb),.4);font-family:'Jost',sans-serif;font-weight:400;font-size:0.75rem;letter-spacing:.08em;padding:0.5rem 0.75rem;white-space:nowrap}
.cm-tip.leaflet-tooltip-top::before{border-top-color:var(--gold-soft)}
/* popup card */
.cm-popup .leaflet-popup-content-wrapper{background:var(--ivory);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-lift)}
.cm-popup .leaflet-popup-content{margin:0}
.cm-popup .leaflet-popup-tip{background:var(--ivory);border:1px solid var(--line)}
/* SPOT-LOT MAP CARD — anatomy, not decoration.
   The Red Tag badge and "Ask me about this home" used to be siblings in the
   normal flow: an inline-block immediately followed by the link. At the popup's
   natural width they wrapped onto the same line and touched. They now live in
   .cm-card__actions, a flex row of their own with a rule above it and a 16px
   minimum gap, and the row wraps to two lines rather than letting them collide.
   Padding is 20px on every side, matching the site's card anatomy. */
.cm-card{padding:20px;min-width:200px}
.cm-card__loc{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.18em;font-size:0.625rem;font-weight:500;color:var(--gold)}
.cm-card__name{font-family:'Cormorant Garamond',serif;font-size:1.5rem;font-weight:600;color:var(--midnight);margin:0.25rem 0 0.25rem;line-height:1.1}
.cm-card__price{font-family:'Cormorant Garamond',serif;font-size:1rem;color:var(--gold);margin:0 0 0.35rem}
/* Lot size, straight from the county parcel record (build/parcel_lots.py). */
.cm-card__lot{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.06em;
  color:var(--muted);margin:0 0 0.35rem}
.cm-card__actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:16px;margin-top:14px;padding-top:12px;border-top:1px solid var(--line)}
.cm-card__link{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.18em;font-size:0.75rem;font-weight:500;color:var(--midnight);border:0;border-bottom:1px solid var(--gold);padding:0 0 2px;background:none;cursor:pointer;text-align:left;line-height:1.3}
.cm-card__link:hover{color:var(--gold)}
.cm-card__link:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
/* Below ~260px of card the two cannot sit side by side with 16px between them,
   so the badge takes its own line rather than being squeezed. */
@media (max-width:400px){
  .cm-card__actions{flex-direction:column;align-items:flex-start;gap:12px}
}
.leaflet-bar a{color:var(--midnight)!important}
.leaflet-control-attribution{font-size:9px;opacity:.7}
@media (max-width:640px){ .community-map{height:380px} }
/* Marion Oaks spot-lot maps */
.marion-map{height:520px;width:100%;border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);background:var(--map-surface);z-index:var(--z-local-raise)}
.marion-map--partner{height:560px}
.marion-count{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.18em;font-size:0.625rem;font-weight:500;color:var(--gold);margin-top:0.5rem}
.marion-legend{display:flex;gap:1.5rem;justify-content:center;flex-wrap:wrap;margin-top:1rem}
.marion-legend__item{display:inline-flex;align-items:center;gap:0.5rem;font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.06em;color:var(--muted)}
.cm-dot{width:14px;height:14px;border-radius:50%;display:inline-block}
.cm-dot--mir{background:var(--midnight);border:2px solid var(--gold)}
.cm-dot--uc{background:var(--gold);border:2px solid var(--midnight)}
.cm-pin--uc .cm-pin__dot{background:var(--gold);border-color:var(--midnight)}
.marion-un{max-width:720px;margin:2rem auto 0;text-align:center}
.marion-un__head{font-family:'Cormorant Garamond',serif;font-size:1.25rem;color:var(--midnight);margin:0 0 0.25rem}
.marion-un__note{font-family:'Jost',sans-serif;font-size:0.875rem;color:var(--muted);margin:0 0 1rem;line-height:1.5}
.marion-un__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:0.5rem}
.marion-un__item{display:flex;align-items:center;gap:1rem;flex-wrap:wrap;justify-content:center;padding:0.75rem 1rem;border:1px solid var(--line);border-radius:var(--radius);background:var(--cream)}
.marion-un__lead{font-family:'Jost',sans-serif;font-weight:500;color:var(--midnight);font-size:0.875rem}
.marion-un__sub{font-family:'Jost',sans-serif;color:var(--gold);font-size:0.875rem}
.marion-un .badge{position:static;font-size:0.625rem}
@media (max-width:640px){ .marion-map,.marion-map--partner{height:400px} }

/* ============ Red Tag treatment (refined, no clearance-sale) ============ */
.badge--redtag{left:1rem;right:auto;background:var(--redtag);color:var(--ivory);
  border-color:rgba(var(--ivory-rgb),.35);letter-spacing:.2em;font-weight:500}
.cm-dot--rt{width:14px;height:14px;border-radius:50%;display:inline-block;background:var(--redtag);border:2px solid var(--ivory);box-shadow:0 0 0 1px var(--redtag)}
.cm-pin--rt .cm-pin__dot{box-shadow:0 0 0 3px var(--redtag),0 3px 10px rgba(var(--midnight-rgb),.5)}
.cm-card__rt{display:inline-block;background:var(--redtag);color:var(--ivory);font-family:'Jost',sans-serif;
  text-transform:uppercase;letter-spacing:.16em;font-size:0.625rem;font-weight:500;padding:0.25rem 0.5rem;border-radius:var(--radius);margin:0;flex:none;white-space:nowrap}
.plan__rt{display:inline-flex;align-items:center;gap:0.25rem;font-family:'Jost',sans-serif;text-transform:uppercase;
  letter-spacing:.14em;font-size:0.625rem;color:var(--redtag);font-weight:500;white-space:nowrap}
/* community-page Red Tag toggle */
.rt-toggle{margin-top:1rem;display:inline-flex;align-items:center;gap:0.5rem;background:transparent;cursor:pointer;
  border:1px solid var(--line);border-radius:var(--radius);padding:0.5rem 1rem;font-family:'Jost',sans-serif;
  text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;color:var(--midnight);transition:all var(--dur-2) var(--ease)}
.rt-toggle:hover{border-color:var(--redtag)}
.rt-toggle.is-on{background:var(--redtag);color:var(--ivory);border-color:var(--redtag)}
.rt-toggle.is-on .cm-dot--rt{border-color:var(--ivory)}
.grid.rt-only .home[data-redtag="0"]{display:none}
/* community card: Red Tag chip + photo-less placeholder */
.card__tag--rt{background:var(--redtag);color:var(--ivory);border-color:transparent;top:auto;bottom:1rem;right:1rem;left:auto}
.card__media--ph{display:flex;align-items:center;justify-content:center;position:relative;min-height:210px;
  background:linear-gradient(140deg,var(--midnight) 0%,var(--midnight-3) 100%)}
.card__ph-name{font-family:'Cormorant Garamond',serif;font-size:2rem;font-weight:600;color:var(--ivory);text-align:center;padding:0 1rem}
.card__media--ph::after{content:"";position:absolute;bottom:1.1rem;left:1.2rem;width:32px;height:1px;background:var(--gold)}
.page-hero__img--ph{position:absolute;inset:0;z-index:var(--z-local-behind);background:linear-gradient(140deg,var(--midnight) 0%,var(--midnight-3) 60%,var(--midnight-2) 100%)}

/* ============ area group headers (communities section) ============ */
.area-head{grid-column:1/-1;display:flex;align-items:baseline;gap:1rem;margin:3rem 0 0.5rem;padding-bottom:0.75rem;border-bottom:1px solid var(--line)}
.area-head:first-child{margin-top:0}
/* Each area reads as its own block: generous air, then a thin champagne rule,
   then the header. `.is-first` is set by filters.js on the first VISIBLE group,
   because filtering can hide the group that happens to be first in source. */
.cgroup{margin-top:4rem;padding-top:3rem;border-top:1px solid rgba(var(--gold-rgb),.5)}
.cgroup:first-child,.cgroup.is-first{margin-top:0;padding-top:0;border-top:0}
.cgroup .area-head{margin-top:0}
@media (max-width:760px){.cgroup{margin-top:3rem;padding-top:2rem}}
.area-head__eyebrow{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.24em;font-size:0.625rem;color:var(--gold);font-weight:500}
.area-head__title{font-family:'Cormorant Garamond',serif;font-size:1.5rem;font-weight:600;color:var(--midnight);margin:0}
.area-head__count{margin-left:auto;font-family:'Jost',sans-serif;font-size:0.75rem;color:var(--muted);letter-spacing:.06em}

/* ============ pin-check tool ============ */
.pc-wrap{display:grid;grid-template-columns:1fr 320px;gap:1.5rem}
.pincheck-map{height:640px;border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);background:var(--map-surface);z-index:var(--z-local-raise)}
.pc-side{display:flex;flex-direction:column;gap:1rem;min-width:0}
.pc-paste-box{border:1px solid var(--line);border-radius:var(--radius);padding:1rem 1rem;background:var(--ivory)}
.pc-paste-box label{display:block;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.12em;font-size:0.75rem;color:var(--gold);margin-bottom:0.5rem}
.pc-paste-row{display:flex;gap:0.5rem}
.pc-paste-row input{flex:1;min-width:0;border:1px solid var(--line);border-radius:var(--radius);padding:0.5rem 0.5rem;font-size:0.875rem;font-family:'Jost',sans-serif}
.pc-paste-row input.pc-paste--err{border-color:var(--redtag)}
.pc-paste-row button{background:var(--midnight);color:var(--ivory);border:none;border-radius:var(--radius);padding:0.5rem 1rem;font-size:0.75rem;text-transform:uppercase;letter-spacing:.1em;cursor:pointer}
.pc-readout{border:1px solid var(--line);border-radius:var(--radius);padding:1rem;background:var(--cream);min-height:120px}
.pc-readout__coord{font-family:'Cormorant Garamond',serif;font-size:1.5rem;color:var(--midnight);margin:0 0 0.25rem}
.pc-readout__near{font-family:'Jost',sans-serif;font-size:0.75rem;color:var(--muted);margin:0 0 0.75rem}
.pc-readout__copy{display:flex;gap:0.5rem;align-items:center}
.pc-readout__copy code{flex:1;font-size:0.75rem;background:var(--ivory);border:1px solid var(--line);padding:0.5rem 0.5rem;border-radius:var(--radius);overflow:auto;white-space:nowrap}
.pc-readout__copy button{background:var(--midnight);color:var(--ivory);border:none;border-radius:var(--radius);padding:0.5rem 0.75rem;font-size:0.75rem;text-transform:uppercase;letter-spacing:.1em;cursor:pointer}
.pc-readout__hint{font-family:'Jost',sans-serif;font-size:0.75rem;color:var(--muted);margin:0.5rem 0 0}
.pc-list{list-style:none;margin:0;padding:0;max-height:480px;overflow:auto;border:1px solid var(--line);border-radius:var(--radius)}
.pc-row{display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0.75rem;border-bottom:1px solid var(--line);cursor:pointer;font-family:'Jost',sans-serif;font-size:0.75rem}
.pc-row:hover{background:var(--cream)}
.pc-row__name{flex:1;color:var(--midnight)}
.pc-row__src{font-size:0.75rem;text-transform:uppercase;letter-spacing:.1em;padding:0.25rem 0.5rem;border-radius:var(--radius)}
.pc-src--centroid{background:rgba(var(--verified-rgb),.14);color:var(--verified)}
.pc-src--fallback{background:rgba(var(--redtag-rgb),.14);color:var(--redtag)}
.pc-src--manual{background:rgba(var(--gold-rgb),.18);color:var(--gold)}
.pc-row__co{font-size:0.75rem;color:var(--muted);white-space:nowrap}
@media (max-width:820px){ .pc-wrap{grid-template-columns:1fr} .pincheck-map{height:440px} }

/* home card: elegant placeholder when a plan has no photo anywhere */
.home__media--ph{display:flex;align-items:center;justify-content:center;position:relative;
  background:linear-gradient(140deg,var(--midnight) 0%,var(--midnight-2) 100%)}
.home__media--ph::before{content:"D\00B7R\00B7 Horton Plan";position:absolute;top:1rem;left:1.1rem;
  font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.22em;font-size:0.75rem;color:var(--gold-soft)}
.home__media--ph::after{content:"";position:absolute;bottom:1.1rem;left:1.1rem;width:34px;height:1px;background:var(--gold)}
.home__ph-name{font-family:'Cormorant Garamond',serif;font-size:2rem;font-weight:600;color:var(--ivory);letter-spacing:.01em;text-align:center;padding:0 1rem}
/* Buyer-card meta as labelled stacked rows (Homesite / Lot / Move-in). The fixed
   rem label column aligns the three values; authored tracks are rem+fr (never px),
   so audit_proportions' fixed-track check does not flag it. */
.home__site{margin:0.6rem 0 0;display:flex;flex-direction:column;gap:0.3rem}
.home__meta-row{display:grid;grid-template-columns:5rem 1fr;align-items:baseline;column-gap:0.75rem}
.home__meta-k{font-size:0.625rem;text-transform:uppercase;letter-spacing:.14em;color:var(--muted);font-family:'Jost',sans-serif}
.home__meta-v{font-size:0.75rem;letter-spacing:.03em;color:var(--ink)}

/* =================================================================
   BATCH: filters, estimator, incentives, compare, home actions
   ================================================================= */
.home__actions{display:flex;flex-direction:column;align-items:flex-start;gap:0.75rem;margin-top:1.5rem}
.home__actions .home__link{margin-top:0}
/* ESTIMATE PAYMENT — the card's primary action, deliberately outweighing
   "View This Home" beneath it. The card's ::after overlay already carries the
   whole surface to the home page, so the text link is a duplicate route; the
   estimator is the only thing here that cannot be reached another way with this
   home's own price, HOA and CDD in it. Solid midnight against a hairline text
   link is the same primary/secondary pair the floor-plan cards use for
   brochure-vs-video, so the hierarchy reads the same everywhere.
   Full-width: at 3-up the label wraps to two lines on a narrow column, and a
   shrink-wrapped button made those two lines ragged against the price above. */
.home__pay{display:inline-flex;align-items:center;justify-content:center;gap:0.5rem;
  width:100%;box-sizing:border-box;padding:0.8rem 1rem;
  font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.16em;
  font-size:0.75rem;font-weight:600;text-align:center;line-height:1.35;
  color:var(--ivory);background:var(--midnight);border:1px solid var(--midnight);
  border-radius:var(--radius);
  transition:background var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease),color var(--dur-2) var(--ease)}
.home__pay:hover{background:var(--gold);border-color:var(--gold);color:var(--midnight)}
.home__pay .arw{color:inherit;transition:transform var(--dur-2) var(--ease);display:inline-block}
.home__pay:hover .arw{transform:translateX(4px)}
/* The secondary route steps back so the pair reads as one primary + one aside,
   not two equal links — it was the same .link-more size and weight as the CTA. */
.home__actions .link-more{font-size:0.6875rem;letter-spacing:.18em;color:var(--muted-aa)}
.home__actions .link-more:hover{color:var(--gold)}
/* PAYMENT DOOR ONLY. /find-your-home prints a monthly payment on the card, so
   the estimator is a sideways route there, not the answer — it reverts to the
   quiet text link it has always been rather than competing with the figure and
   the door's own filters. See home_card(payment=True) in build/generate.py. */
.home__pay--quiet{width:auto;padding:0;background:none;border:0;color:var(--midnight);
  font-weight:500;letter-spacing:.2em;justify-content:flex-start;
  padding-bottom:3px;background-image:linear-gradient(var(--gold),var(--gold));
  background-size:0% 1px;background-repeat:no-repeat;background-position:0 100%;
  transition:background-size var(--dur-3) var(--ease),color var(--dur-2) var(--ease)}
.home__pay--quiet:hover{background:none;color:var(--gold);
  background-image:linear-gradient(var(--gold),var(--gold));background-size:100% 1px;
  background-repeat:no-repeat;background-position:0 100%}
.home__pay--quiet .arw{color:var(--gold)}
.home__broc{display:inline-flex;align-items:center;gap:0.5rem;margin-top:1rem;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.11em;font-size:0.75rem;font-weight:500;color:var(--midnight);border:1px solid var(--line);border-radius:var(--radius);padding:0.5rem 0.75rem;transition:border-color var(--dur-2) var(--ease),color var(--dur-2) var(--ease)}
.home__broc svg{width:13px;height:13px;flex:none}
.home__broc:hover{border-color:var(--gold);color:var(--gold)}
.home__broc--req{border-style:dashed;color:var(--muted)}

/* ---- Floor-plan filter/sort bar ---- */
.fp-controls{margin-bottom:1.5rem}
.fp-toggle{display:none;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.16em;font-size:0.75rem;font-weight:500;padding:1rem 1.5rem;border:1px solid var(--midnight);border-radius:var(--radius);background:transparent;color:var(--midnight);cursor:pointer;width:100%}
.fp-inner{display:flex;flex-wrap:wrap;align-items:center;gap:1rem 2rem;padding:1.5rem 1.5rem;background:var(--white);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
.fp-group{display:flex;align-items:center;gap:0.75rem;flex-wrap:wrap}
.fp-label{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.16em;font-size:0.625rem;font-weight:500;color:var(--gold)}
.fp-pills{display:flex;gap:0.5rem;flex-wrap:wrap}
.fp-pills button{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.05em;padding:0.5rem 0.75rem;border:1px solid var(--line);border-radius:var(--radius);background:transparent;color:var(--ink);cursor:pointer;transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease)}
.fp-pills button:hover{border-color:var(--gold)}
.fp-pills button.is-on{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}
.fp-controls select{font-family:'Jost',sans-serif;font-size:0.75rem;padding:0.5rem 0.75rem;border:1px solid var(--line);border-radius:var(--radius);background:var(--ivory);color:var(--ink);cursor:pointer}
.fp-checks{gap:1rem}
.fp-checks label{display:inline-flex;align-items:center;gap:0.5rem;font-size:0.75rem;cursor:pointer;color:var(--ink)}
.fp-checks input{accent-color:var(--gold)}
.fp-clear{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;color:var(--muted);background:none;border:none;cursor:pointer;text-decoration:underline;text-underline-offset:3px}
.fp-clear:hover{color:var(--gold)}
.fp-count{text-align:center;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;color:var(--muted);margin:0 0 2rem}
@media (max-width:820px){
  .fp-toggle{display:inline-flex;justify-content:center}
  .fp-inner{display:none;flex-direction:column;align-items:flex-start;margin-top:0.75rem}
  .fp-controls.fp-open .fp-inner{display:flex}
}

/* ---- Payment estimator ---- */
.est{display:grid;grid-template-columns:1.15fr 1fr;gap:2rem;align-items:start;max-width:960px;margin:0 auto}
/* Grid items default to min-width:auto, so ANY unbreakable child can push a track
   wider than its column. Belt-and-braces after the .btn--full overflow above. */
.est > *{min-width:0}
.est__inputs{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);padding:2rem;box-shadow:var(--shadow);display:grid;gap:1.5rem}
.est__field{display:grid;gap:0.5rem}
.est__field > span{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;font-weight:500;color:var(--midnight);display:flex;align-items:center}
.est__field > span b{color:var(--gold);font-weight:600}
.est__field input[type=text]{font-family:'Cormorant Garamond',serif;font-size:1.5rem;font-weight:600;padding:0.5rem 1rem;border:1px solid var(--line);border-radius:var(--radius);background:var(--ivory);color:var(--midnight)}
.est__pills{display:flex;gap:0.5rem;flex-wrap:wrap}
.est__pills button{font-family:'Jost',sans-serif;font-size:0.75rem;padding:0.5rem 0.75rem;border:1px solid var(--line);border-radius:var(--radius);background:transparent;color:var(--ink);cursor:pointer;transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease)}
.est__pills button.is-on{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}
/* DOWN-PAYMENT CHIPS carry two lines: the percentage, and what it costs at the
   current price. GRID, not the flex the other pill rows use — five two-line
   chips wrapped by flex come out ragged (2/2/1 with three different widths on a
   phone), and a price is easiest to compare down a column of equal boxes. The
   auto-fit is deliberate rather than a fixed `repeat(5,1fr)`: a track can never
   be narrower than its floor, so the row drops to two columns on a phone rather
   than squeezing five chips until "$65,998" spills — the 320px failure mode
   this section has hit before. 68px IS that widest amount (0.68rem) plus the
   chip's padding, and it lands five across in the desktop input column.
   Tabular numerals stop the amounts from jittering as the price is typed. */
.est__pills--down{display:grid;grid-template-columns:repeat(auto-fit,minmax(68px,1fr))}
.est__pills--down button{display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:0.15rem;line-height:1.2;min-width:0;padding:0.5rem}
.est__pill-amt{font-family:'Jost',sans-serif;font-size:0.68rem;letter-spacing:.01em;
  font-variant-numeric:tabular-nums;opacity:.68}
.est__pills--down button.is-on .est__pill-amt{opacity:.85}
/* LOAN TYPE (dark behind config.LOAN_TYPE_ENABLED). Two wide options rather
   than the compact down-payment grid: this is the choice that changes what
   every other control means, so it reads as a decision, not a nudge. The
   explanatory note sits under it because "FHA" and "Conventional" are not
   self-describing to the person this estimator is for — the difference in the
   payment is the whole reason the toggle exists, so it is stated in words
   beside the control that produces it. */
/* THREE PROGRAMS, THREE COLUMNS (VA added 2026-08-02). auto-fit with a 92px
   floor rather than repeat(3,1fr): at 375px inside the estimator's own padding
   three equal columns give each pill ~86px, and "Conventional" needs ~104px at
   this tracking — it wrapped mid-word. auto-fit drops to two columns and then
   one as the space demands, so the longest label is never broken. */
.est__pills--loan{display:grid;grid-template-columns:repeat(auto-fit,minmax(92px,1fr));gap:0.5rem}
.est__pills--loan button{min-height:44px;letter-spacing:.06em;white-space:nowrap}
.est__loan-note{margin:0.15rem 0 0;font-family:'Jost',sans-serif;font-size:0.7rem;
  line-height:1.65;letter-spacing:.01em;color:var(--muted-aa)}
/* The VA paragraph sits under the FHA/Conventional one and carries the same
   treatment — it is a third explainer, not a footnote to the other two. The
   <b> runs (no monthly MI, the disability waiver) are the two facts a veteran
   is actually scanning for. */
.est__loan-note + .est__loan-note{margin-top:var(--sp-3)}
.est__loan-note b{font-weight:500;color:var(--ink)}
/* A hidden chip set must be GONE, not just invisible: .est__pills--down is a
   grid, and display:grid on a [hidden] element beats the UA sheet's
   display:none and would render both programs' chips at once. */
.est__pills--down[hidden]{display:none}
/* THIS HOME'S FIXED COSTS. Deliberately NOT a control: no border, no field
   affordance, no hover — it has to read as a printed fact beside the things
   that do move, or a visitor will hunt for the slider that isn't there. */
.est__fixed{gap:0.6rem}
.est__fixed-rows{display:grid;gap:0.35rem;margin:0;padding:0.75rem 0.9rem;
  background:var(--ivory);border-radius:var(--radius)}
.est__fixed-row{display:flex;align-items:baseline;justify-content:space-between;gap:1rem}
.est__fixed-row dt{font-family:'Jost',sans-serif;font-size:0.8rem;color:var(--muted)}
.est__fixed-row dd{margin:0;font-family:'Jost',sans-serif;font-size:0.85rem;
  font-weight:500;color:var(--midnight);font-variant-numeric:tabular-nums}
.est__fixed-note{font-family:'Jost',sans-serif;font-size:0.7rem;line-height:1.45;
  color:var(--muted);margin:0}
.est__fixed[hidden]{display:none}
.est__field input[type=range]{width:100%;accent-color:var(--gold)}
.est__output{background:var(--midnight);color:var(--ivory);border-radius:var(--radius);padding:2rem 2rem;text-align:center;box-shadow:var(--shadow-lift)}
.est__label{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.16em;font-size:0.75rem;color:var(--gold-soft);margin-top:1.5rem}
.est__label:first-child{margin-top:0}
.est__big{font-family:'Cormorant Garamond',serif;font-size:clamp(1.75rem,7.2vw,2.75rem);font-weight:600;color:var(--ivory);line-height:1.05;white-space:nowrap;min-width:0;overflow-wrap:normal}
.est__big--sub{font-size:2rem;color:var(--gold-soft)}
.est__detail{font-size:0.75rem;letter-spacing:.02em;color:rgba(var(--ivory-rgb),.6);margin:0.75rem 0 0.5rem}
.est__basis{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.02em;color:rgba(var(--ivory-rgb),.72);margin:0 0 0.5rem}
.est__note{font-family:'Jost',sans-serif;font-size:0.75rem;line-height:1.5;color:var(--gold-soft);margin:0 0 1.5rem;font-style:italic}
@media (max-width:760px){.est{grid-template-columns:1fr}}

/* ---- Incentives ---- */
.adv{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);padding:2rem;box-shadow:var(--shadow)}
.adv h3{font-size:1.25rem;font-weight:600;margin-bottom:0.5rem}
.adv p{color:var(--muted);font-size:1rem;font-weight:300}
.adv--feature{grid-column:1/-1;background:var(--midnight);color:var(--ivory);display:flex;flex-direction:column;justify-content:center;padding:2rem}
.adv--feature h3{color:var(--ivory);font-size:clamp(1.6rem,3vw,2.2rem)}
.adv--feature p{color:rgba(var(--ivory-rgb),.86);font-size:1rem}
.adv__tag{display:inline-block;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.22em;font-size:0.625rem;color:var(--gold-soft);margin-bottom:0.75rem}
.fineprint{max-width:760px;margin:2rem auto 0;text-align:center;font-size:0.75rem;color:var(--muted-aa);line-height:1.7}
/* A link in fineprint was indistinguishable from the text around it: the global
   rule is a{color:inherit;text-decoration:none}, so it inherited --muted-aa and
   carried no underline — same colour, no affordance, not discoverable as a link
   at all (WCAG 1.4.1). Same treatment as .dsc__credit a / .page-hero__credit a.
   The colour stays inherited ON PURPOSE: --muted-aa is 4.95:1 on --ivory (AA for
   normal text), where --gold is 2.50:1 and would have failed. The underline is
   the affordance; the contrast is unchanged from the text it sits in. */
.fineprint a{color:inherit;text-decoration:underline;text-underline-offset:2px}
.est__disclaimer{max-width:860px}

/* ---- Compare communities ---- */
.cmp-chips{display:flex;flex-wrap:wrap;gap:0.5rem;justify-content:center;margin-bottom:2rem}
.cmp-chip{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.12em;font-size:0.75rem;font-weight:500;padding:0.5rem 1rem;border:1px solid var(--line);border-radius:var(--radius);background:transparent;color:var(--ink);cursor:pointer;transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease)}
.cmp-chip:hover{border-color:var(--gold)}
.cmp-chip.is-on{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}
.cmp-chip:disabled{opacity:.38;cursor:not-allowed}
.cmp-empty{text-align:center;color:var(--muted)}
.cmp-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(248px,1fr));gap:1.5rem;max-width:980px;margin:0 auto}
.cmp-card{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);padding:2rem;box-shadow:var(--shadow);display:flex;flex-direction:column}
.cmp-card__loc{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.16em;font-size:0.625rem;color:var(--gold)}
.cmp-card__name{font-family:'Cormorant Garamond',serif;font-size:1.5rem;font-weight:600;margin:0.25rem 0 1rem;line-height:1.1}
.cmp-dl{margin:0 0 1.5rem}
.cmp-row{padding:0.75rem 0;border-top:1px solid var(--line)}
.cmp-row dt{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.12em;font-size:0.75rem;color:var(--muted);margin-bottom:0.25rem}
.cmp-row dd{font-size:1rem;color:var(--ink)}
.cmp-card .btn{margin-top:auto}

/* nav: Realtor Partners — subtle gold accent, last before Contact */
.nav__partner{display:inline-flex;align-items:center;gap:.55rem;color:var(--gold-soft)!important;opacity:1!important;border:1px solid rgba(var(--gold-soft-rgb),.5);border-radius:999px;padding:.5rem .95rem;background:rgba(var(--gold-soft-rgb),.06);transition:transform var(--dur-2) var(--ease),background var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease)}
.nav__partner::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--gold);box-shadow:0 0 0 0 rgba(var(--gold-soft-rgb),.5);animation:navpulse 2.6s ease-in-out infinite}
.nav__partner:hover{transform:translateY(-1px);background:rgba(var(--gold-soft-rgb),.15);border-color:var(--gold-soft);box-shadow:0 6px 18px rgba(var(--black-rgb),.28);color:var(--ivory)!important}
/* slow, subtle ring — a quiet breath, never a blink */
@keyframes navpulse{0%{box-shadow:0 0 0 0 rgba(var(--gold-soft-rgb),.45)}60%{box-shadow:0 0 0 5px rgba(var(--gold-soft-rgb),0)}100%{box-shadow:0 0 0 0 rgba(var(--gold-soft-rgb),0)}}
@media (prefers-reduced-motion:reduce){.nav__partner::before{animation:none}}
/* partners: why-partner strip */
.whypartner .wp{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);padding:1.5rem;box-shadow:var(--shadow)}
.whypartner .wp h3{font-size:1.25rem;font-weight:600;margin-bottom:0.5rem}
.whypartner .wp p{color:var(--muted);font-size:0.875rem;font-weight:300}
@media (max-width:900px){.whypartner{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.whypartner{grid-template-columns:1fr}}

/* ============ Chat widget — "Tony's Assistant" ============ */
.tgchat-launch{position:fixed;right:1.5rem;bottom:1.5rem;z-index:var(--z-chat-launcher);display:inline-flex;align-items:center;gap:0.5rem;
  background:var(--midnight);color:var(--ivory);border:1px solid var(--gold);border-radius:40px;padding:0.75rem 1rem;
  font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.08em;cursor:pointer;box-shadow:0 10px 30px rgba(var(--midnight-rgb),.4);
  transition:transform var(--dur-2) var(--ease),background var(--dur-2) var(--ease),opacity var(--dur-1) var(--ease)}
.tgchat-launch svg{width:20px;height:20px;color:var(--gold-soft)}
.tgchat-launch:hover{transform:translateY(-2px);background:var(--midnight-2)}
.tgchat-launch.is-hidden{opacity:0;pointer-events:none;transform:translateY(10px)}
/* THE FACE ON THE BUTTON. The initials sit underneath and the photograph over
   them, so a 404 on the headshot degrades to "TG" in a champagne ring rather
   than to an empty circle. Both are the same 30px box, so nothing reflows. */
.tgchat-launch{padding-left:0.4rem}
.tgchat-launch__av{position:relative;width:30px;height:30px;flex:none;border-radius:50%;
  overflow:hidden;border:1.5px solid var(--gold-soft);background:var(--midnight-2)}
.tgchat-launch__av img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:50% 22%}
.tgchat-launch__ini{position:absolute;inset:0;display:grid;place-items:center;
  font-family:'Jost',sans-serif;font-size:0.6875rem;letter-spacing:.06em;color:var(--gold-soft)}
.tgchat-launch__lbl{letter-spacing:.14em;text-transform:uppercase}
/* FIRST VISIT ONLY (assets/chat.js writes tg_chat_seen on first paint). A ring
   that expands and fades once every few seconds — an attention cue, not an
   alarm. Reduced-motion turns it off entirely rather than slowing it down:
   the cue is decorative and nothing depends on seeing it. */
.tgchat-launch__pulse{display:none}
.tgchat-launch.is-new .tgchat-launch__pulse{display:block;position:absolute;
  inset:-3px;border-radius:44px;border:1.5px solid var(--gold-soft);
  animation:tgring 2.6s ease-out infinite;pointer-events:none}
@keyframes tgring{0%{opacity:.75;transform:scale(1)}70%{opacity:0;transform:scale(1.14)}100%{opacity:0;transform:scale(1.14)}}
@media (prefers-reduced-motion:reduce){.tgchat-launch.is-new .tgchat-launch__pulse{animation:none;opacity:.5}}

/* ---- proactive teaser ----
   A message preview sitting directly above the launcher, which is itself
   already anchored above the Call/Text bar — so the teaser can never cover
   the call bar, and being bottom-anchored it can never cover a hero CTA.
   It is a peer of the launcher rather than a child, so hiding the launcher on
   open does not take a half-faded teaser with it. */
.tgchat-teaser{position:fixed;right:1.5rem;z-index:var(--z-chat-launcher);
  bottom:calc(1.5rem + 58px);display:flex;align-items:flex-start;gap:0.5rem;
  width:min(300px,calc(100vw - 3rem));padding:0.7rem 0.75rem;
  background:var(--white);border:1px solid var(--line);border-radius:12px;
  border-bottom-right-radius:3px;box-shadow:0 14px 40px rgba(var(--midnight-rgb),.28);
  opacity:0;transform:translateY(10px);pointer-events:none;
  transition:opacity var(--dur-2) var(--ease),transform var(--dur-2) var(--ease)}
.tgchat-teaser.is-in{opacity:1;transform:none;pointer-events:auto}
.tgchat-teaser__av{width:32px;height:32px;flex:none;border-radius:50%;object-fit:cover;
  object-position:50% 22%;border:1.5px solid var(--gold-soft)}
.tgchat-teaser__msg{flex:1;min-width:0;text-align:left;background:none;border:none;
  padding:0;cursor:pointer;font-family:'Jost',sans-serif;font-size:0.8125rem;
  line-height:1.45;color:var(--midnight)}
.tgchat-teaser__x{flex:none;background:none;border:none;cursor:pointer;
  font-size:1.1rem;line-height:1;color:var(--muted-aa);padding:0 0.15rem;
  /* 24px is under the 44px tap target the sweep prefers, so the hit area is
     expanded with padding-box rather than by making the glyph bigger. */
  min-width:28px;min-height:28px}
.tgchat-teaser__x:hover{color:var(--midnight)}
@media (prefers-reduced-motion:reduce){.tgchat-teaser{transition:none}}
.tgchat-panel{position:fixed;right:1.5rem;bottom:1.5rem;z-index:calc(var(--z-chat-launcher) + 1);width:380px;max-width:calc(100vw - 3rem);height:560px;max-height:calc(100dvh - 3rem);
  display:flex;flex-direction:column;background:var(--ivory);border:1px solid var(--line);border-radius:10px;overflow:hidden;
  box-shadow:0 24px 70px rgba(var(--midnight-rgb),.34);opacity:0;transform:translateY(16px) scale(.98);pointer-events:none;transition:opacity var(--dur-2) var(--ease),transform var(--dur-2) var(--ease)}
.tgchat-panel.is-open{opacity:1;transform:none;pointer-events:auto}
.tgchat-head{display:flex;align-items:center;gap:0.75rem;padding:1rem 1rem;background:var(--midnight);color:var(--ivory)}
.tgchat-head__avwrap{position:relative;width:44px;height:44px;flex:none;border-radius:50%;
  overflow:hidden;border:1.5px solid var(--gold-soft);background:var(--midnight-2);
  box-shadow:0 2px 8px rgba(var(--black-rgb),.28)}
.tgchat-head__ini{position:absolute;inset:0;display:grid;place-items:center;
  font-family:'Jost',sans-serif;font-size:0.875rem;letter-spacing:.06em;color:var(--gold-soft)}
.tgchat-head__avatar{position:absolute;inset:0;width:100%;height:100%;border-radius:0;
  object-fit:cover;object-position:50% 22%;border:none;box-shadow:none}
.tgchat-head__meta{flex:1;min-width:0}
.tgchat-head__name{font-family:'Cormorant Garamond',serif;font-size:1.25rem;font-weight:600;margin:0;line-height:1.1}
.tgchat-head__sub{display:flex;align-items:center;gap:0.5rem;font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.09em;text-transform:uppercase;color:var(--gold-soft);margin:0.25rem 0 0}
.tgchat-dot{width:8px;height:8px;border-radius:50%;background:var(--success);flex:none;box-shadow:0 0 0 0 rgba(var(--success-rgb),.7);animation:tgpulse 2s infinite}
@keyframes tgpulse{0%{box-shadow:0 0 0 0 rgba(var(--success-rgb),.55)}70%{box-shadow:0 0 0 6px rgba(var(--success-rgb),0)}100%{box-shadow:0 0 0 0 rgba(var(--success-rgb),0)}}
@media (prefers-reduced-motion:reduce){.tgchat-dot{animation:none}}
.tgchat-x{background:none;border:none;color:var(--ivory);font-size:1.5rem;line-height:1;cursor:pointer;opacity:.8;padding:0 0.25rem}
.tgchat-x:hover{opacity:1}
.tgchat-log{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;padding:1rem;display:flex;flex-direction:column;gap:0.5rem;background:var(--cream)}
.tgchat-msg{max-width:84%;padding:0.75rem 1rem;border-radius:12px;font-family:'Jost',sans-serif;font-size:0.875rem;line-height:1.5;white-space:pre-wrap;word-wrap:break-word}
.tgchat-msg--assistant{align-self:flex-start;background:var(--white);color:var(--midnight);border:1px solid var(--line);border-bottom-left-radius:3px}
.tgchat-msg--user{align-self:flex-end;background:var(--midnight);color:var(--ivory);border-bottom-right-radius:3px}
/* Assistant messages ride in a row beside Tony's headshot. The bubble keeps its
   own styling; the row takes over the flex-column alignment it used to own. */
.tgchat-row{display:flex;align-items:flex-end;gap:0.5rem;align-self:flex-start;max-width:92%}
.tgchat-row .tgchat-msg--assistant{align-self:auto;max-width:100%}
.tgchat-av{width:28px;height:28px;border-radius:50%;object-fit:cover;object-position:50% 22%;flex:none;border:1.5px solid var(--gold-soft);box-shadow:0 1px 4px rgba(var(--black-rgb),.18);margin-bottom:2px}
.tgchat-typing{display:flex;gap:4px;align-items:center}
.tgchat-typing span{width:6px;height:6px;border-radius:50%;background:var(--muted);animation:tgblink 1.2s infinite}
.tgchat-typing span:nth-child(2){animation-delay:.2s}.tgchat-typing span:nth-child(3){animation-delay:.4s}
@keyframes tgblink{0%,60%,100%{opacity:.3}30%{opacity:1}}
/* REG Z INSIDE THE BUBBLE. Quiet, but not hidden: it is a full sentence at a
   readable size, sitting on a hairline under the figure it qualifies, inside
   the same bubble. Never a tooltip, never collapsed, never in the footer. */
.tgchat-terms{margin:0.55rem 0 0;padding-top:0.5rem;border-top:1px solid var(--line);
  font-size:0.6875rem;line-height:1.5;color:var(--muted-aa);white-space:normal}
/* ---- quick replies ----
   One scrolling row above the input. They are shortcuts, so they must not
   push the input field off a phone screen — one row, horizontally scrollable,
   no wrap. */
.tgchat-quick{display:flex;gap:0.4rem;padding:0.6rem 0.75rem 0;background:var(--ivory);
  overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.tgchat-quick::-webkit-scrollbar{display:none}
.tgchat-quick:empty{display:none}
.tgchat-chip{flex:none;white-space:nowrap;font-family:'Jost',sans-serif;font-size:0.6875rem;
  letter-spacing:.05em;padding:0.45rem 0.7rem;min-height:32px;cursor:pointer;
  color:var(--midnight);background:var(--white);border:1px solid var(--line);
  border-radius:99px;text-decoration:none;display:inline-flex;align-items:center;
  transition:border-color var(--dur-1) var(--ease)}
.tgchat-chip:hover{border-color:var(--gold)}
/* The exit to a human reads as the exit to a human. */
.tgchat-chip--sms{border-color:var(--gold);color:var(--gold-deep)}
/* SMS consent row — sits between the quick replies and the composer, revealed
   by assets/chat.js only once a reply asks for a number. `hidden` must win over
   the flex display or the row shows on every conversation. */
.tgchat-consent{display:flex;align-items:flex-start;gap:0.5rem;
  padding:0.625rem 0.875rem 0;background:var(--ivory);
  font-family:'Jost',sans-serif;font-size:0.6875rem;line-height:1.5;font-weight:300;
  color:var(--muted);cursor:pointer}
.tgchat-consent[hidden]{display:none}
.tgchat-consent input{flex:none;width:17px;height:17px;margin-top:0.15rem;accent-color:var(--gold)}
.tgchat-consent a{color:var(--midnight);border-bottom:1px solid var(--gold)}
.tgchat-form{display:flex;gap:0.5rem;padding:0.75rem;border-top:1px solid var(--line);background:var(--ivory)}
.tgchat-input{flex:1;min-width:0;border:1px solid var(--line);border-radius:22px;padding:0.75rem 1rem;font-family:'Jost',sans-serif;font-size:16px;outline:none}
.tgchat-input:focus{border-color:var(--gold)}
.tgchat-send{flex:none;width:42px;height:42px;border-radius:50%;background:var(--midnight);color:var(--ivory);border:1px solid var(--gold);font-size:1rem;cursor:pointer}
.tgchat-send:hover{background:var(--midnight-2)}
.tgchat-foot{margin:0;padding:0.5rem 1rem 0.75rem;font-family:'Jost',sans-serif;font-size:0.625rem;color:var(--muted);text-align:center;background:var(--ivory)}
@media (max-width:560px){
  .tgchat-panel{right:0;bottom:0;width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0}
  .tgchat-launch{right:1rem;bottom:1rem;padding:0.75rem 1rem}
  body.tgchat-lock{overflow:hidden}
}

/* Keep the chat widget clear of the sticky mobile Call/Text bar — chat moves, never the bar */
@media (max-width:640px){
  .tgchat-launch{bottom:calc(var(--callbar-h) + 12px)}
  .tgchat-panel{bottom:calc(var(--callbar-h) + 12px);max-height:calc(100dvh - var(--callbar-h) - 2.5rem)}
}
@media (max-width:560px){
  /* fullscreen panel must sit ABOVE the bar, never cover it */
  .tgchat-launch{right:1rem;bottom:calc(var(--callbar-h) + 12px)}
  .tgchat-panel{right:0;width:100vw;max-width:100vw;bottom:var(--callbar-h);
    height:calc(100dvh - var(--callbar-h));max-height:calc(100dvh - var(--callbar-h))}
  /* The quick-reply row is the first thing to give up space when the on-screen
     keyboard halves the sheet — but it is never dropped, because the exit to a
     human lives in it. */
  .tgchat-quick{padding:0.45rem 0.6rem 0}
  .tgchat-chip{font-size:0.65rem;padding:0.4rem 0.6rem}
}
/* THE TEASER TRACKS THE LAUNCHER, at every breakpoint, because the launcher is
   what is already positioned clear of the Call/Text bar (and of .pbar on
   /partners). 58px is the launcher's own height plus its 12px gap; keeping the
   teaser a fixed distance above it means neither can ever cover the bar, and
   the sweep's "control the user cannot escape" test has nothing to find. */
@media (max-width:640px){
  .tgchat-teaser{right:1rem;bottom:calc(var(--callbar-h) + 12px + 58px);
    width:min(300px,calc(100vw - 2rem))}
  body.partners .tgchat-teaser{bottom:calc(var(--pbar-h) + 12px + 58px)}
}
/* Never both at once: an open panel replaces the teaser. */
body.tgchat-open .tgchat-teaser{display:none}
/* video tour download — self-hosted mp4, styled to match the brochure action */
.plan__act--viddl{background:none;color:var(--muted);border:1px solid var(--line)}
.plan__act--viddl:hover{border-color:var(--gold);color:var(--gold)}

/* --- Red Tag featured card: first thing a realtor sees on /partners --- */
.prog--feature{grid-column:1 / -1;border-top-width:3px;background:
  linear-gradient(180deg,rgba(var(--gold-soft-rgb),.10),rgba(var(--gold-soft-rgb),0) 55%),var(--white)}
.prog--feature .prog__name{font-size:2rem}
.prog--feature .prog__badge{font-size:0.625rem;padding:0.5rem 0.75rem}
.prog__figure{font-family:'Cormorant Garamond',serif;font-size:2.75rem;font-weight:600;color:var(--midnight);
  line-height:1;margin:0.25rem 0 0rem;display:flex;align-items:baseline;gap:0.5rem;flex-wrap:wrap}
.prog__figure span{font-family:'Jost',sans-serif;font-size:0.625rem;font-weight:500;letter-spacing:.18em;
  text-transform:uppercase;color:var(--muted)}
.prog__figure em{font-family:'Jost',sans-serif;font-style:normal;font-size:0.75rem;font-weight:400;
  letter-spacing:.06em;color:var(--gold);align-self:center}
@media (min-width:900px){ .prog--feature .prog__headline{font-size:1.5rem} }
/* inventory item: name + last-updated date */
.flyer__meta{display:flex;flex-direction:column;gap:0.25rem;min-width:0;text-align:left}
.flyer__date{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.08em;color:var(--muted)}
.flyer{border:none;cursor:pointer;width:100%;font:inherit;text-align:left}
/* four-up sticky bar */
@media (max-width:640px){
  .pbar{grid-template-columns:repeat(4,1fr)}
  .pbar__btn{font-size:0.75rem;letter-spacing:.08em}
}
/* BUTTON RESET ONLY — never typography. `font:inherit` used to live here, and
   the shorthand quietly reset font-size, font-weight, font-style and
   line-height along with the family. Three of the four .home__broc emitters
   are <button> (brochure viewer, video tour) and one is an <a> (the
   brochure-on-request mailto), so the same control rendered at the inherited
   1rem/400 as a button and at .75rem/500 as a link — side by side in the same
   .home__assets row on every card that had a video. Uniform typography is the
   whole point of the class, so the reset is now scoped to the things a UA
   actually gets wrong on a <button>: chrome, cursor, and the fact that a
   button does not inherit font-family at all. Size, weight, tracking and case
   come from .home__broc above and from nowhere else. */
.home__broc{background:none;cursor:pointer;font-family:'Jost',sans-serif;
  font-size:0.75rem;font-weight:500;font-style:normal;line-height:1.2}

/* --- unified viewer: video mode --- */
.bv__video{display:none;width:100%;max-height:80dvh;background:var(--video-bg)}
.bv.is-video .bv__stage picture{display:none}
.bv.is-video .bv__video{display:block}
.bv.is-video .bv__stage{overflow:visible;touch-action:auto}
/* --- badge band: badges get their own zone, never over text --- */
.home__badges{position:absolute;top:0;left:0;right:0;z-index:var(--z-local-over);display:flex;align-items:flex-start;
  justify-content:flex-start;gap:0.5rem;padding:1rem;pointer-events:none}
.home__badges .badge{position:static;top:auto;right:auto;left:auto}
.home__badge--status{margin-left:auto}
/* ---- real listing photos: carousel + chip -------------------------------
   The chip sits at the BOTTOM-LEFT, structurally separate from the top badge
   band (Red Tag left / status right), so the two can never collide no matter
   how long either label gets. Dots take the bottom-right for the same reason. */
/* .badge--real ("REAL PHOTOS") WAS REMOVED 2026-07-27, RULE AND STYLE BOTH.
   It was emitted whenever the photo manifest held any entry for a home, which
   included every card whose lead slide is the plan's elevation RENDERING — so
   it captioned artist's art as photography on a public page. The rule is gone
   as well as the markup, because a dead rule is how a component comes back.
   Any future photo-truth badge needs per-image provenance, not a manifest
   count; see build/generate.py home_card() and the gate in audit_cards.py. */
.hcar{touch-action:pan-y}
.hcar__track{display:flex;height:100%;width:100%;
  transition:transform var(--dur-3) var(--ease);will-change:transform}
.hcar__slide{flex:0 0 100%;width:100%;height:100%;display:block}
.hcar__slide img{width:100%;height:100%;object-fit:cover;display:block}
/* the dots sit on whatever the photo happens to be — a bright sky washed
   them out completely, so they carry their own scrim. */
.hcar__dots{position:absolute;bottom:.85rem;right:.85rem;z-index:var(--z-local-control);display:flex;gap:0.25rem;
  padding:0.25rem 0.5rem;border-radius:99px;background:rgba(var(--midnight-rgb),.42);backdrop-filter:blur(3px)}
.hcar__dot{width:7px;height:7px;border-radius:50%;border:0;padding:0;cursor:pointer;
  background:rgba(var(--ivory-rgb),.62);transition:background var(--dur-2) var(--ease),transform var(--dur-2) var(--ease)}
.hcar__dot.is-on{background:var(--gold);transform:scale(1.25)}
.hcar__arw{position:absolute;top:50%;transform:translateY(-50%);z-index:var(--z-local-control);width:34px;height:34px;
  border-radius:50%;border:1px solid rgba(var(--gold-soft-rgb),.5);background:rgba(var(--midnight-rgb),.55);
  backdrop-filter:blur(4px);color:var(--ivory);font-size:1rem;line-height:1;cursor:pointer;
  opacity:0;transition:opacity var(--dur-2) var(--ease),background var(--dur-2) var(--ease)}
.hcar__arw--prev{left:.6rem}
.hcar__arw--next{right:.6rem}
.hcar:hover .hcar__arw,.hcar__arw:focus-visible{opacity:1}
.hcar__arw:hover{background:var(--gold);color:var(--midnight)}
/* Touch devices have no hover, and a permanently-visible arrow over a photo
   looks like a mistake — swipe and the dots carry it there. */
@media (hover:none){ .hcar__arw{display:none} }
/* Placeholder cards put the badge band in NORMAL FLOW so the plan name can only
   ever occupy the space left over — overlap is impossible at any text size. */
.home__media--ph{display:flex;flex-direction:column;align-items:stretch;justify-content:flex-start;padding-top:0}
.home__media--ph .home__badges{position:static;flex:none}
.home__media--ph .home__ph-name{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;
  padding:0.25rem 1rem 1rem;overflow:hidden}
.home__assets{display:flex;flex-wrap:wrap;gap:0.5rem;margin-top:1rem}
.home__assets .home__broc{margin-top:0}
.home__vid svg{width:13px;height:13px}
.flyer-actions{gap:0.75rem;flex-wrap:wrap}

/* --- desktop hover preview (pointer devices only) --- */
.bvpv{position:fixed;z-index:calc(var(--z-modal) + 1);width:380px;padding:6px;background:var(--white);
  border:1px solid var(--gold-soft);border-radius:var(--radius);box-shadow:0 18px 50px rgba(var(--midnight-rgb),.28);
  opacity:0;visibility:hidden;transform:translateY(4px);pointer-events:none;
  transition:opacity var(--dur-1) var(--ease),transform var(--dur-1) var(--ease),visibility var(--dur-1)}
.bvpv.is-on{opacity:1;visibility:visible;transform:none}
.bvpv__img{display:block;width:100%;height:auto;border-radius:1px}
@media (hover:none),(pointer:coarse){.bvpv{display:none!important}}

/* --- mobile chat viewport: sized from visualViewport so the keyboard can't
       cut off the header or lose scroll position (JS sets --tgvh/--tgvtop) --- */
body.tgchat-open{overflow:hidden;overscroll-behavior:none}
@media (max-width:560px){
  /* THE PANEL OPENS OVER THE PAGE, IT DOES NOT REPLACE IT (brief section 5).
     It used to take the full dynamic viewport — top:0, height:100dvh — so the
     homes list underneath was not merely covered but gone, and closing the
     chat read as a navigation back rather than a dismissal. Worse, --tgvh is
     set from the visual viewport, so when the keyboard closed and the value
     lagged a frame the sheet kept its shortened height against a full-height
     body and left a band of dead space below it with nothing rendered in it.

     A SHEET WITH A CEILING FIXES BOTH. It is bottom-anchored and capped at
     88% of the viewport, so the list is always visible above it — the page is
     still there, which is what makes this a panel and not a screen — and any
     lag in --tgvh shortens the sheet from a bottom edge that is pinned to the
     bottom of the screen, so the gap it would have left is off-screen instead
     of inside the layout. */
  .tgchat-panel.is-open{
    top:auto;
    bottom:var(--callbar-h,0px);
    height:auto;
    max-height:min(88dvh, calc(var(--tgvh, 100dvh) - 2.5rem));
    border-radius:14px 14px 0 0;
  }
  /* The call bar stays put. It was hidden so the panel could own the screen;
     the panel no longer owns the screen, and hiding a fixed element on open
     collapsed its height and shifted the page under the sheet. */
  body.tgchat-open .pbar{display:none!important}
}

/* =============================================================================
   BROCHURE VIEWER — full-screen page-image lightbox (no PDF embed).
   RESTORED: this block was deleted by a CSS block-replacement during the Programs
   redesign, which made the JS-injected overlay render inline as page content.
   ========================================================================== */
.bv{position:fixed;inset:0;z-index:var(--z-modal);background:rgba(var(--midnight-rgb),.97);
  display:flex;align-items:center;justify-content:center;
  opacity:0;visibility:hidden;transition:opacity var(--dur-2) var(--ease),visibility var(--dur-2)}
.bv.is-open{opacity:1;visibility:visible}
body.bv-open{overflow:hidden}
.bv__bar{position:absolute;top:0;left:0;right:0;display:flex;align-items:center;gap:1rem;
  padding:0.75rem 1rem;background:linear-gradient(to bottom,rgba(var(--midnight-rgb),.95),rgba(var(--midnight-rgb),0));z-index:var(--z-local-over)}
.bv__id{flex:1;min-width:0}
.bv__title{font-family:'Cormorant Garamond',serif;font-size:1.25rem;font-weight:600;color:var(--ivory);
  margin:0;line-height:1.1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bv__count{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--gold-soft);margin:0.25rem 0 0}
.bv__variants{display:flex;gap:0.5rem;flex:none}
.bv__variant{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.12em;text-transform:uppercase;
  font-weight:500;color:var(--gold-soft);background:none;border:1px solid rgba(var(--gold-soft-rgb),.45);
  border-radius:999px;padding:0.5rem 0.75rem;cursor:pointer;transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.bv__variant.is-on{background:var(--gold-soft);color:var(--midnight);border-color:var(--gold-soft)}
.bv__dl{display:inline-flex;align-items:center;gap:0.5rem;flex:none;font-family:'Jost',sans-serif;
  font-size:0.75rem;letter-spacing:.12em;text-transform:uppercase;font-weight:500;
  color:var(--midnight);background:var(--gold-soft);border-radius:var(--radius);padding:0.5rem 0.75rem}
.bv__dl svg{width:13px;height:13px}
.bv__dl:hover{background:var(--gold)}
.bv__x{flex:none;width:44px;height:44px;display:flex;align-items:center;justify-content:center;
  background:none;border:none;color:var(--ivory);font-size:2rem;line-height:1;cursor:pointer;opacity:.85}
.bv__x:hover{opacity:1;color:var(--gold-soft)}
.bv__stage{max-width:min(94vw,1000px);max-height:88dvh;overflow:auto;-webkit-overflow-scrolling:touch;
  touch-action:pinch-zoom;overscroll-behavior:contain;border-radius:2px;box-shadow:0 30px 90px rgba(var(--black-rgb),.6)}
.bv__img{display:block;width:100%;height:auto;background:var(--white);transition:transform var(--dur-2) var(--ease);transform-origin:center top}
.bv__img.is-zoomed{transform:scale(2)}
.bv__nav{position:absolute;top:50%;transform:translateY(-50%);width:52px;height:52px;z-index:var(--z-local-over);
  display:flex;align-items:center;justify-content:center;font-size:2rem;line-height:1;cursor:pointer;
  color:var(--ivory);background:rgba(var(--midnight-rgb),.55);border:1px solid rgba(var(--gold-soft-rgb),.3);border-radius:50%;
  transition:background var(--dur-1) var(--ease),opacity var(--dur-1) var(--ease)}
.bv__nav:hover{background:rgba(var(--gold-soft-rgb),.9);color:var(--midnight)}
.bv__nav:disabled{opacity:.25;cursor:default}
.bv__nav--prev{left:1rem}
.bv__nav--next{right:1rem}
.bv__video{display:none;width:100%;max-height:80dvh;background:var(--video-bg)}
.bv.is-video .bv__stage picture{display:none}
.bv.is-video .bv__video{display:block}
.bv.is-video .bv__stage{overflow:visible;touch-action:auto}

/* PLAN DETAIL: the walkthrough and the plan's availability in one overlay.
   Side by side above 900px, stacked below it — on a phone the video keeps the
   top of the viewport and the community list scrolls under it, because an agent
   on site is reading the list, not watching the tour a second time.
   The panel is hidden unless .is-plandetail is set, so the plain video and
   brochure modes are untouched. */
.bv__avail{display:none}
.bv.is-plandetail{align-items:stretch;justify-content:flex-start;gap:0;padding:4.25rem 1rem 1rem}
.bv.is-plandetail .bv__stage{flex:1 1 58%;max-width:none;align-self:center}
.bv.is-plandetail .bv__nav{display:none}
.bv.is-plandetail .bv__avail{display:block;flex:0 0 clamp(320px,34%,460px);margin-left:1.25rem;
  overflow:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;max-height:100%;
  border-left:1px solid rgba(var(--gold-soft-rgb),.25);padding-left:1.25rem}
.bv__avail-head{margin:0 0 1rem}
.bv__avail-head h4{font-family:'Cormorant Garamond',serif;font-size:1.35rem;font-weight:600;
  color:var(--ivory);margin:0 0 .25rem;line-height:1.15}
.bv__avail-head p,.bv__avail-load,.bv__avail-empty{font-family:'Jost',sans-serif;font-size:.8rem;
  letter-spacing:.06em;color:var(--gold-soft);margin:0}
.bv__mkt{margin:0 0 1.25rem}
.bv__mkt h5{font-family:'Jost',sans-serif;font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;
  font-weight:500;color:var(--gold-soft);margin:0 0 .5rem;padding-bottom:.35rem;
  border-bottom:1px solid rgba(var(--gold-soft-rgb),.2)}
.bv__comm{display:grid;grid-template-columns:1fr auto;gap:.15rem .75rem;padding:.6rem 0;
  border-bottom:1px solid rgba(var(--ivory-rgb),.08);text-decoration:none}
.bv__comm:hover{background:rgba(var(--gold-soft-rgb),.07)}
.bv__comm-name{font-family:'Jost',sans-serif;font-size:.95rem;font-weight:500;color:var(--ivory)}
.bv__55{display:inline-block;margin-left:.4rem;font-size:.6rem;letter-spacing:.1em;font-weight:600;
  color:var(--midnight);background:var(--gold-soft);border-radius:999px;padding:.1rem .4rem;vertical-align:middle}
.bv__comm-n{font-family:'Jost',sans-serif;font-size:.75rem;color:var(--gold-soft);text-align:right}
/* --redtag (#8a2f38) is the sitewide token, but it is a deep burgundy tuned for
   light backgrounds and fails contrast on this near-black overlay. Rendered as
   the gold-on-burgundy pill the overlay already uses for emphasis instead. */
.bv__rt{color:var(--ivory);background:var(--redtag);font-weight:600;
  border-radius:999px;padding:.1rem .45rem;font-size:.68rem;letter-spacing:.04em}
.bv__comm-price{font-family:'Jost',sans-serif;font-size:.85rem;font-weight:500;color:var(--ivory);
  grid-column:1/-1}
.bv__comm-spec,.bv__comm-hoa{font-family:'Jost',sans-serif;font-size:.72rem;letter-spacing:.04em;
  color:rgba(var(--ivory-rgb),.62);grid-column:1/-1}
@media (max-width:900px){
  .bv.is-plandetail{flex-direction:column;align-items:stretch;padding:4rem .75rem .75rem}
  .bv.is-plandetail .bv__stage{flex:0 0 auto;align-self:stretch}
  .bv.is-plandetail .bv__avail{flex:1 1 auto;margin:1rem 0 0;border-left:none;padding-left:0;
    border-top:1px solid rgba(var(--gold-soft-rgb),.25);padding-top:1rem}
}
@media (max-width:640px){
  .bv__stage{max-width:100vw;max-height:calc(100dvh - 132px);margin-top:56px}
  .bv__nav{width:46px;height:46px;top:auto;bottom:1rem;transform:none}
  .bv__nav--prev{left:1.2rem}
  .bv__nav--next{right:1.2rem}
  .bv__title{font-size:1rem}
  .bv__dl span{display:none}
  .bv__dl{padding:0.5rem 0.75rem}
  body.bv-open .tgchat-launch,body.bv-open .mobile-callbar,body.bv-open .pbar{display:none!important}
}

/* =============================================================================
   THE SHORTLIST — full-screen wizard. Split layout (imagery left, steps right),
   midnight/ivory/champagne, Cormorant display. Mobile-first: aside collapses.
   ========================================================================== */
.sl{position:fixed;inset:0;z-index:var(--z-modal);display:grid;grid-template-columns:38% 1fr;
  background:var(--ivory);opacity:0;visibility:hidden;transition:opacity var(--dur-2) var(--ease),visibility var(--dur-2)}
.sl.is-open{opacity:1;visibility:visible}
body.sl-open{overflow:hidden}
.sl__aside{position:relative;background:linear-gradient(160deg,var(--midnight),var(--midnight-2));color:var(--ivory);
  display:flex;align-items:center;overflow:hidden}
.sl__aside::after{content:"";position:absolute;inset:0;background:url(/assets/photos/planlib-hayden.jpg) center/cover;
  opacity:.16;mix-blend-mode:luminosity}
.sl__asideInner{position:relative;z-index:var(--z-local-raise);padding:3rem 3rem}
.sl__kicker{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.24em;text-transform:uppercase;
  color:var(--gold-soft);margin:0 0 0.75rem}
.sl__asideTitle{font-family:'Cormorant Garamond',serif;font-size:2.75rem;font-weight:600;line-height:1.05;
  color:var(--ivory);margin:0 0 2rem}
.sl__dots{display:flex;gap:0.5rem}
.sl__dot{width:26px;height:2px;background:rgba(var(--ivory-rgb),.22);border-radius:2px;transition:background var(--dur-2) var(--ease)}
.sl__dot.is-on{background:var(--gold-soft)}
.sl__dot.is-done{background:rgba(var(--gold-soft-rgb),.55)}
.sl__main{position:relative;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:3rem 3rem 3rem}
/* THE CLOSE CONTROL. Anchored to .sl (which never scrolls), not to .sl__main
   (which does) — see the note in assets/shortlist.js. z-index 200 clears the
   sticky refine bar (2), the mobile sheet scrim (170) and the sheet itself
   (180), so it stays tappable even with the bottom sheet up. It is a solid chip
   rather than a bare glyph because it now sits over whatever the results happen
   to be scrolled to, not over a predictable blank corner. */
.sl__x{position:absolute;z-index:var(--z-local-control);top:.9rem;right:1rem;width:44px;height:44px;
  display:flex;align-items:center;justify-content:center;
  background:var(--white);border:1px solid var(--line);border-radius:99px;
  font-size:1.5rem;line-height:1;color:var(--midnight);cursor:pointer;opacity:1;
  box-shadow:0 4px 14px -6px rgba(var(--midnight-rgb),.42);
  transition:border-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.sl__x:hover,.sl__x:focus-visible{border-color:var(--gold);color:var(--gold)}
.sl__body{max-width:640px;margin:0 auto}
.sl__stepno{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--muted);margin:0 0 0.5rem}
.sl__q{font-family:'Cormorant Garamond',serif;font-size:2rem;font-weight:600;color:var(--midnight);
  margin:0 0 0.5rem;line-height:1.15}
.sl__sub{font-size:0.875rem;color:var(--muted-aa);font-weight:400;margin:0 0 1.5rem}
.sl__opts{display:grid;gap:0.75rem;margin:1.5rem 0 1.5rem}
.sl__opts--2{grid-template-columns:1fr 1fr}
.sl__opts--3{grid-template-columns:repeat(3,1fr)}
.sl__opts--photo{grid-template-columns:repeat(3,1fr)}
.sl__opt{display:flex;flex-direction:column;align-items:flex-start;gap:0.5rem;min-height:56px;
  padding:1rem 1rem;background:var(--white);border:1px solid var(--line);border-radius:var(--radius);
  cursor:pointer;font:inherit;text-align:left;transition:border-color var(--dur-1) var(--ease),transform var(--dur-1) var(--ease)}
.sl__opt:hover{border-color:var(--gold);transform:translateY(-2px)}
.sl__opt.is-on{border-color:var(--gold);background:rgba(var(--gold-soft-rgb),.10);box-shadow:inset 0 0 0 1px var(--gold)}
.sl__optImg{display:block;width:100%;aspect-ratio:4/3;border-radius:2px;background:var(--cream) center/cover}
.sl__optLabel{font-family:'Jost',sans-serif;font-size:0.875rem;color:var(--midnight)}
/* --- Zero-result state + suggested adjustments ---------------------------
   A dead end is the one thing this quiz is not allowed to be. When the hard
   filters return nothing, this is what the visitor gets instead: the reason,
   stated plainly, and one-tap doors with real counts on them. Styled as
   ACTIONS, not as an error — the gold rule and the tappable rows read as the
   next step, because that is what they are.                                  */
.sl__empty{margin:0 0 1.5rem;padding:1.25rem 1.25rem 1rem;background:var(--cream);
  border:1px solid var(--line);border-left:3px solid var(--gold);border-radius:var(--radius)}
.sl__emptyLine{font-family:'Cormorant Garamond',serif;font-size:1.375rem;line-height:1.3;
  color:var(--midnight);margin:0 0 0.75rem}
.sl__empty .sl__sub{margin:0 0 0.75rem}
.sl__sugs{display:flex;flex-direction:column;gap:0.5rem}
.sl__sug{display:block;width:100%;text-align:left;font-family:'Jost',sans-serif;font-size:0.875rem;
  color:var(--midnight);background:var(--white);border:1px solid var(--line);border-radius:var(--radius);
  padding:0.75rem 1rem;min-height:44px;cursor:pointer;
  transition:border-color var(--dur-1) var(--ease),transform var(--dur-1) var(--ease)}
.sl__sug:hover{border-color:var(--gold);transform:translateY(-1px)}
/* On the dark hero card the same block has to stop being cream-on-cream. */
.hsl .sl__empty{background:rgba(var(--midnight-rgb),.62);border-color:rgba(var(--ivory-rgb),.24)}
.hsl .sl__emptyLine{color:var(--ivory);font-size:1.125rem}
.hsl .sl__sug{color:var(--ivory);background:rgba(var(--ivory-rgb),.06);
  border-color:rgba(var(--ivory-rgb),.24)}
.sl__nav{display:flex;gap:0.75rem;margin-top:0.5rem}
.sl__btn{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;
  font-weight:500;color:var(--ivory);background:var(--midnight);border:1px solid var(--midnight);
  border-radius:var(--radius);padding:0.75rem 1.5rem;cursor:pointer;transition:background var(--dur-2) var(--ease)}
.sl__btn:hover{background:var(--gold);border-color:var(--gold);color:var(--midnight)}
.sl__btn--ghost{background:none;color:var(--midnight)}
.sl__btn--full{width:100%;margin-top:0.75rem}
.sl__agentFields{display:grid;gap:1rem;margin:1rem 0}
.sl__agentFields label,.sl__lead label{display:block;font-family:'Jost',sans-serif;font-size:0.75rem;
  letter-spacing:.16em;text-transform:uppercase;color:var(--muted);margin-bottom:1rem}
.sl__agentFields input,.sl__lead input{display:block;width:100%;margin-top:0.5rem;padding:0.75rem 1rem;
  border:1px solid var(--line);border-radius:var(--radius);font-family:'Jost',sans-serif;font-size:16px;
  color:var(--ink);background:var(--white)}
/* results */
.sl__agentNote{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.08em;color:var(--gold);
  background:rgba(var(--gold-soft-rgb),.12);border-radius:var(--radius);padding:0.5rem 1rem;margin:0 0 1rem}
.sl__cards{display:grid;gap:1rem;margin:1rem 0 2rem}
/* THE THUMBNAIL USED TO STRETCH, AND THAT IS WHAT CUT THE HOUSES IN HALF.
   The image cell was a grid track with no height of its own, so it took the
   height of the BODY beside it — 340-380px of tier badge, specs, price, HOA and
   two buttons — inside a 132px column. `cover` then scaled a 1200x900 exterior
   to cover 360px of height and showed the middle ~27% of its width: a front
   door and half a garage. Every card cropped differently, because every card's
   body is a different height.
   Fix: the image is top-aligned and owns a FIXED 4:3 box, so it is the same
   shape on every card and the photo is never scaled past what it can fill.
   `min-height:0` is load-bearing — grid items default to min-height:auto, which
   would let the old min-height:132px fight the aspect ratio. */
.sl__card{position:relative;display:grid;grid-template-columns:168px 1fr;gap:1rem;align-items:start;
  background:var(--white);padding:1rem 0 1rem 1rem;
  border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow)}
.sl__cardImg{position:relative;aspect-ratio:4/3;min-height:0;border-radius:2px;
  background:var(--cream) center 45%/cover no-repeat}
.sl__rt{position:absolute;top:.5rem;left:.5rem;background:var(--redtag);color:var(--ivory);
  font-family:'Jost',sans-serif;font-size:0.625rem;font-weight:600;letter-spacing:.14em;padding:0.25rem 0.5rem;border-radius:2px}
.sl__cardBody{padding:0 1rem 0 0;min-width:0}
.sl__near{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--gold);margin:0 0 0.25rem}
.sl__cardComm{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted-aa);margin:0}
.sl__cardPlan{font-family:'Cormorant Garamond',serif;font-size:1.5rem;font-weight:600;margin:0rem 0 0.25rem;color:var(--midnight)}
.sl__cardSpecs{font-size:0.75rem;color:var(--muted-aa);margin:0;font-variant-numeric:tabular-nums}
.sl__cardPrice{font-family:'Cormorant Garamond',serif;font-size:1.5rem;font-weight:600;color:var(--midnight);margin:0.25rem 0 0}
.sl__cardStage{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted-aa);margin:0rem 0 0}
.sl__why{list-style:none;padding:0;margin:0.5rem 0 0;display:flex;flex-wrap:wrap;gap:0.25rem}
.sl__why li{font-family:'Jost',sans-serif;font-size:0.75rem;color:var(--midnight);background:var(--cream);
  border-radius:99px;padding:0.25rem 0.5rem}
.sl__plan{margin-top:0.75rem;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.12em;
  font-size:0.75rem;color:var(--midnight);background:none;border:1px solid var(--line);border-radius:var(--radius);
  padding:0.5rem 0.75rem;cursor:pointer}
.sl__plan:hover{border-color:var(--gold);color:var(--gold)}
/* ---- Shortlist: horizontal bands, tier badges, result actions ------------
   Bands are full-width rows so the price spread reads as a spectrum you move
   along, not four boxes to pick between. The count on the right is live. */
.sl__bands{display:flex;flex-direction:column;gap:0.5rem;margin:1rem 0 1.5rem}
.sl__bands--tight{margin:0.5rem 0 1rem}
.sl__band{display:grid;grid-template-columns:1fr auto;align-items:baseline;gap:0.25rem 0.75rem;width:100%;
  text-align:left;background:none;border:1px solid var(--line);border-radius:var(--radius);
  padding:0.75rem 1rem;cursor:pointer;font-family:inherit;
  transition:border-color var(--dur-2) var(--ease),background var(--dur-2) var(--ease),transform var(--dur-2) var(--ease)}
.sl__band:hover{border-color:var(--gold);transform:translateX(2px)}
.sl__band.is-on{border-color:var(--gold);background:rgba(var(--gold-soft-rgb),.1)}
.sl__bandLabel{font-family:'Jost',sans-serif;font-size:1rem;color:var(--midnight);font-weight:400;font-variant-numeric:tabular-nums;letter-spacing:.01em}
.sl__bandSub{grid-column:1;font-size:0.75rem;color:var(--muted-aa);font-weight:400}
.sl__bandN{grid-row:1;grid-column:2;font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted-aa);white-space:nowrap;font-variant-numeric:tabular-nums}
.sl__label{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--gold);margin:1rem 0 0rem}
.sl__skip{display:inline-block;background:none;border:0;padding:0;margin:-0.5rem 0 0.5rem;cursor:pointer;
  font-family:'Jost',sans-serif;font-size:0.75rem;color:var(--muted-aa);border-bottom:1px solid var(--line)}
.sl__skip:hover{color:var(--gold);border-color:var(--gold)}
.sl__optFrom{display:block;font-size:0.75rem;color:var(--muted-aa);letter-spacing:0;text-transform:none;margin-top:0.25rem;font-variant-numeric:tabular-nums}
.sl__optN{display:inline-block;margin-left:0.5rem;font-size:0.625rem;color:var(--muted-aa);font-variant-numeric:tabular-nums}
.sl__tier{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.14em;text-transform:uppercase;
  font-weight:500;margin:0 0 0.25rem;display:inline-block;padding:0.25rem 0.5rem;border-radius:99px}
.sl__tier--strong{color:var(--verified-ink);background:rgba(var(--verified-ink-rgb),.1)}
.sl__tier--close{color:var(--warning-ink);background:rgba(var(--gold-soft-rgb),.22)}
.sl__tier--look{color:var(--muted);background:var(--cream)}
.sl__villa{margin-left:0.5rem;color:var(--gold)}
.sl__cardActs{display:flex;flex-wrap:wrap;gap:0.5rem;margin-top:0.75rem}
.sl__cardActs .sl__plan{margin-top:0}
@media(max-width:560px){
  .sl__band{padding:0.75rem 0.75rem}
  .sl__bandLabel{font-size:0.875rem}
}
/* ---- Shortlist: the estimator bridge on each result card ------------------
   Small and champagne, sitting under the price. Deliberately quiet: it is a
   next step, not a second call to action competing with the lead form. */
.sl__cardEst{margin:0.25rem 0 0}
.sl__cardEst a{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.08em;color:var(--gold);
  text-decoration:none;border-bottom:1px solid rgba(var(--gold-soft-rgb),.5);padding-bottom:1px}
.sl__cardEst a:hover{color:var(--midnight);border-color:var(--midnight)}

/* ---- Shortlist: the refine bar -------------------------------------------
   Results are an adjustable workspace, not a verdict. The bar sticks to the top
   of the results list on desktop; below 640px it becomes a bottom sheet behind
   an "Adjust results" pill so the cards stay visible while you tune them.
   NOTE: the 640px breakpoint is duplicated in isSheet() in assets/shortlist.js.
   Change one and you must change the other. */
/* THE REFINE PANEL OUTRANKS EVERY CARD — and it did not, which is why card
   links and buttons painted straight through it while the results scrolled.
   It sat at --z-local-over (2). So do .home__actions and .home__assets, and a
   tie is broken by DOM order, which the cards win because they come after.
   .hcar__arw sits at --z-local-control (3) and beat it outright. Three separate
   card layers were above a panel that is supposed to float over all of them.

   Two changes, both load-bearing:
     * --z-sticky-sub, which is above the entire per-card scale rather than
       inside it. (From the --z-* scale, never a raw number:
       build/audit_stacking.py fails the build on a bare z-index.)
     * isolation:isolate — the panel becomes ONE stacking context, so nothing
       inside a card can ever reach into it again by raising its own z-index.
   The background must also be genuinely opaque; a translucent panel over
   scrolling cards reads as the same bug even when the order is right. */
/* ONLY THE CONDENSED BAR IS STICKY. The full panel sits in normal flow and
   scrolls away like any other block — so it never overlays a card, and the
   card controls underneath stay reachable (build/audit_shortlist.py asserts
   exactly that, and caught this the moment the panel started winning the
   stacking contest it had previously been losing). What pins is the 48px
   summary bar, which is the whole point of condensing. */
.sl__refine{position:relative;z-index:var(--z-sticky-sub);isolation:isolate;
  background:var(--ivory);
  border:1px solid var(--line);border-radius:var(--radius);
  padding:0.75rem 1rem 1rem;margin:0 0 1rem;
  box-shadow:0 6px 18px -14px rgba(var(--midnight-rgb),.5)}

/* CONDENSED STATE. A full-height control panel pinned over a scrolling list is
   the wrong shape even when it stacks correctly — it eats the results it is
   meant to refine. Full panel at the top of the results; once scrolled it
   collapses to a one-line summary of what is currently applied, and a tap puts
   the full panel back. assets/shortlist.js owns the toggle.

   SCOPED TO >=641px ON PURPOSE. Below that breakpoint .sl__refine is not a
   sticky bar at all — it is the bottom SHEET (position:fixed, parked off-screen
   under transform:translateY(101%) + visibility:hidden until .is-sheetOpen),
   opened by .sl__refinePill. Two different designs for one element.

   Unscoped, these rules collided: `.sl__refine.is-condensed` (0,2,0) outranks
   the media query's `.sl__refine` (0,1,0), so on a phone it dragged position
   back to sticky while the sheet's transform and visibility:hidden stayed put.
   The result was an invisible 49px sticky bar, shoved down 49.49px by a
   transform meant for a sheet, that could never win a hit test — so the cards
   underneath painted straight through it. build/audit_scroll_integrity.py
   caught it at 375x812 and nowhere else, which is exactly the fingerprint of a
   breakpoint collision. is-condensed is a desktop affordance; on mobile the
   pill and the sheet already do this job, so below 641px it must stay inert. */
.sl__refBar{display:none}
@media (min-width:641px){
  .sl__refine.is-condensed{position:sticky;top:0;padding:0;overflow:hidden}
  .sl__refine.is-condensed > *:not(.sl__refBar){display:none}
  .sl__refine.is-condensed .sl__refBar{display:flex;align-items:center;gap:0.6rem;
    width:100%;min-height:48px;padding:0.5rem 0.9rem;cursor:pointer;
    background:transparent;border:0;text-align:left;
    font-family:'Jost',sans-serif;font-size:0.78rem;letter-spacing:.02em;color:var(--ink)}
  .sl__refine.is-condensed:hover .sl__refBarCue{text-decoration:underline}
}
.sl__refBarText{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sl__refBarCue{flex:none;font-size:0.7rem;letter-spacing:.14em;text-transform:uppercase;color:var(--gold-deep,var(--gold))}
.sl__refBar:focus-visible{outline:2px solid var(--gold);outline-offset:-2px}
.sl__refHead{display:flex;align-items:baseline;justify-content:space-between;gap:1rem}
.sl__refTitle{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--gold);margin:0 0 0.5rem}
.sl__refDone{display:none}
.sl__refRow{display:flex;align-items:center;flex-wrap:wrap;gap:0.5rem 0.75rem;margin:0.25rem 0}
.sl__refLabel{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted-aa);flex:0 0 5.6rem}
.sl__step{display:flex;align-items:center;gap:0.5rem}
.sl__stepBtn{width:32px;height:32px;flex:0 0 32px;border:1px solid var(--line);border-radius:99px;
  background:var(--white);color:var(--midnight);font-size:1rem;line-height:1;cursor:pointer;
  transition:border-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.sl__stepBtn:hover:not(:disabled){border-color:var(--gold);color:var(--gold)}
.sl__stepBtn:disabled{opacity:.32;cursor:default}
.sl__stepVal{font-family:'Jost',sans-serif;font-size:0.875rem;color:var(--midnight);
  font-variant-numeric:tabular-nums;min-width:9.2rem;text-align:center}
.sl__chips{display:flex;flex-wrap:wrap;gap:0.5rem}
.sl__chip{font-family:'Jost',sans-serif;font-size:0.75rem;color:var(--midnight);background:var(--white);
  border:1px solid var(--line);border-radius:99px;padding:0.5rem 0.75rem;min-height:32px;cursor:pointer;
  transition:border-color var(--dur-1) var(--ease),background var(--dur-1) var(--ease)}
.sl__chip:hover:not(:disabled){border-color:var(--gold)}
.sl__chip:disabled{opacity:.32;cursor:default}
/* Quiz budget tabs — every surface, payment tab first (2026-07-28). */
.sl__tabs{display:flex;gap:8px;margin:0 0 14px}
.sl__tab{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.06em;text-transform:uppercase;
  color:var(--midnight);background:var(--white);border:1px solid var(--line);border-radius:99px;
  padding:0.5rem 0.9rem;min-height:32px;cursor:pointer;
  transition:border-color var(--dur-1) var(--ease),background var(--dur-1) var(--ease)}
.sl__tab:hover{border-color:var(--gold)}
.sl__tab.is-on{border-color:var(--gold);background:rgba(var(--gold-soft-rgb),.10);box-shadow:inset 0 0 0 1px var(--gold)}
/* The secondary budget figure on a payment-door result card. */
.sl__cardAlt{font-family:'Jost',sans-serif;font-size:0.85rem;color:var(--muted-aa);margin:0.1rem 0 0}
/* A2 on the quiz card: the terms that qualify the payment above them. Same
   shape as .home__payterms / .home__paydisc so the two surfaces read alike. */
.sl__cardTerms{font-family:'Jost',sans-serif;font-size:0.7rem;line-height:1.55;
  letter-spacing:.01em;color:var(--muted-aa);margin:0.25rem 0 0}
.sl__cardTerms b{font-weight:600;color:var(--ink);white-space:nowrap}
.sl__cardDisc{font-family:'Jost',sans-serif;font-size:0.63rem;line-height:1.5;
  letter-spacing:.01em;color:var(--muted-aa);margin:0.2rem 0 0}
.sl__regz{margin-top:14px}
/* The guided-start line above the payment grid (generate.py fyh template). */
.fyh__quiz{margin:.4rem 0 0;font-family:'Jost',sans-serif;font-size:.9rem;color:var(--muted-aa)}
.fyh__quizBtn{background:none;border:0;padding:0;font:inherit;color:var(--midnight);text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.fyh__quizBtn:hover{color:var(--gold)}
.sl__chip.is-on{border-color:var(--gold);background:rgba(var(--gold-soft-rgb),.14)}
.sl__chipX{margin-left:0.5rem;color:var(--muted-aa);font-size:0.875rem;line-height:1}
.sl__chip--rm:hover .sl__chipX{color:var(--gold)}
.sl__chip--add{border-style:dashed;color:var(--muted-aa)}
.sl__chips--add{margin:0.5rem 0 0 6rem}
.sl__refCount{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.06em;color:var(--muted-aa);
  margin:0.5rem 0 0;font-variant-numeric:tabular-nums}
.sl__refReset{display:inline-block;background:none;border:0;padding:0;margin:0.25rem 0 0;cursor:pointer;
  font-family:'Jost',sans-serif;font-size:0.75rem;color:var(--muted-aa);border-bottom:1px solid var(--line)}
.sl__refReset:hover{color:var(--gold);border-color:var(--gold)}
/* The re-rank fade. Cards resettle rather than teleport; anyone who asked for
   reduced motion gets the swap instantly (the JS skips the delay entirely). */
.sl__cards{transition:opacity 190ms var(--ease)}
.sl__cards.is-swap{opacity:.15}
@media (prefers-reduced-motion:reduce){
  .sl__cards,.sl__cards.is-swap{transition:none;opacity:1}
}
/* =============================================================================
   SHORTLIST — the 2026-07-28 restructure: chip picks, the location map, the
   clickable card and the collapsed results map.
   ========================================================================== */

/* ---- step 1: the picks, in the filter bar's own chip language -------------
   Deliberately the same shape, weight and count treatment as .flt__pill on
   /homes. A buyer who has used the filter bar already knows what these do, and
   two vocabularies for one idea is exactly the confusion this batch removed. */
.sl__pickRow{margin:0 0 1rem}
.sl__pickRow .sl__label{margin:0 0 0.4rem}
.sl__pills{display:flex;flex-wrap:wrap;gap:0.35rem;min-width:0}
.sl__pill{display:inline-flex;align-items:baseline;gap:0;flex:none;font-family:'Jost',sans-serif;
  font-size:0.75rem;letter-spacing:.04em;padding:0.6rem 0.8rem;min-height:40px;cursor:pointer;
  color:var(--ink);background:transparent;border:1px solid var(--line);border-radius:var(--radius);
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease)}
.sl__pill:hover:not(:disabled){border-color:var(--gold)}
.sl__pill.is-on{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}
/* Half a selection is neither on nor off, and must not pretend to be either:
   an area chip with 3 of its 9 communities picked reads as outlined-gold. */
.sl__pill.is-some{border-color:var(--gold);box-shadow:inset 0 0 0 1px var(--gold)}
.sl__pill.is-void,.sl__pill:disabled{opacity:.4;cursor:default}
.sl__n{font-style:normal;font-size:0.78em;letter-spacing:.06em;font-variant-numeric:tabular-nums;
  color:var(--muted-aa);margin-left:0.55rem;padding-left:0.55rem;
  border-left:1px solid rgba(var(--gold-soft-rgb),.32)}
.sl__n:empty{display:none}
.sl__pill.is-on .sl__n{color:rgba(var(--gold-soft-rgb),.78);border-left-color:rgba(var(--gold-soft-rgb),.38)}
.sl__pill--clear{border-style:dashed;color:var(--muted-aa)}
.sl__pills--area{margin:0 0 0.75rem}
.sl__pills--comms{margin:0.75rem 0 0}

/* ---- step 1: the bypass line and the "More filters" disclosure -----------
   Step 1 stacked four pill rows, and at 1280x900 that put the Next button and
   the Reg Z block below the fold — the buyer saw a wall of chips with no
   visible way forward. Bedrooms, lot size and home type now sit inside a
   closed <details>, so the screen opens on the budget ceiling, the bypass
   promise, and Next. build/audit_quiz_fold.py asserts the button stays in the
   viewport on load and fails the build if it ever drops out again.

   The disclosure is styled to read as a deliberate door, not as a collapsed
   error state: bordered, full-width, with the marker rotated by hand so the
   affordance survives the marker reset browsers disagree on. */
.sl__bypass{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.06em;
  color:var(--gold-deep,var(--gold));margin:0 0 0.85rem;display:flex;gap:0.45rem;align-items:baseline}
.sl__bypass::before{content:"\2713";font-size:0.9em;flex:none}
.hsl .sl__bypass{color:var(--gold-soft)}

.sl__more{margin:0 0 1rem;border:1px solid var(--line);border-radius:var(--radius);
  padding:0 0.85rem;overflow:hidden}
.sl__more[open]{padding-bottom:0.35rem}
.sl__moreSum{display:flex;align-items:center;gap:0.6rem;cursor:pointer;list-style:none;
  font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink);padding:0.85rem 0;min-height:44px;box-sizing:border-box}
.sl__moreSum::-webkit-details-marker{display:none}
.sl__moreSum::after{content:"";flex:none;margin-left:auto;width:0.5rem;height:0.5rem;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:rotate(45deg) translate(-2px,-2px);
  transition:transform var(--dur-1) var(--ease)}
.sl__more[open] .sl__moreSum::after{transform:rotate(-135deg) translate(-2px,-2px)}
.sl__moreSum:hover{color:var(--gold-deep,var(--gold))}
.sl__moreSum:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
/* The count of applied filters — the only thing that tells a buyer the closed
   panel is doing something. Without it a collapsed disclosure silently holds
   an active bedroom filter and the result count looks wrong for no reason. */
.sl__moreN{font-style:normal;font-size:0.9em;letter-spacing:.06em;font-variant-numeric:tabular-nums;
  color:var(--muted-aa);text-transform:none}
.sl__moreSub{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.04em;
  color:var(--muted-aa);margin:0 0 0.85rem}
.sl__more .sl__pickRow:last-of-type{margin-bottom:0.6rem}
.hsl .sl__more{border-color:rgba(var(--ivory-rgb),.28)}
.hsl .sl__moreSum{color:var(--ivory)}
.hsl .sl__moreSub,.hsl .sl__moreN{color:rgba(var(--ivory-rgb),.92)}

/* ---- step 2: the location map -------------------------------------------- */
.sl__map{height:clamp(260px,42vh,420px);width:100%;border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden;background:var(--cream)}
.sl__map--pick{margin:0 0 0.75rem}
.sl__mapOff{font-family:'Jost',sans-serif;font-size:0.75rem;line-height:1.6;color:var(--muted-aa);
  background:var(--cream);border-radius:var(--radius);padding:0.75rem 1rem;margin:0 0 0.5rem}
.sl__selCount{font-family:'Jost',sans-serif;font-size:0.875rem;letter-spacing:.04em;color:var(--midnight);
  font-variant-numeric:tabular-nums;margin:0.25rem 0 1rem}
/* Community pin. Same silhouette as the /map pins so one site has one map. */
.sl-pin{background:none;border:0}
.sl-pin__dot{display:block;width:14px;height:14px;margin:8px;border-radius:50%;
  background:var(--midnight);border:2px solid var(--ivory);
  box-shadow:0 1px 5px rgba(var(--midnight-rgb),.45);
  transition:transform var(--dur-1) var(--ease),background var(--dur-1) var(--ease)}
.sl-pin:hover .sl-pin__dot{transform:scale(1.18)}
.sl-pin.is-on .sl-pin__dot{background:var(--gold);width:18px;height:18px;margin:6px;
  box-shadow:0 0 0 4px rgba(var(--gold-soft-rgb),.35),0 1px 6px rgba(var(--midnight-rgb),.45)}
.sl-pin--home .sl-pin__dot{width:12px;height:12px;margin:7px;background:var(--gold)}
.sl-pin--home.is-hot .sl-pin__dot{background:var(--midnight);
  box-shadow:0 0 0 5px rgba(var(--gold-soft-rgb),.45),0 1px 6px rgba(var(--midnight-rgb),.5)}
.sl__pinNote{font-family:'Jost',sans-serif;font-size:0.6875rem;line-height:1.45;color:var(--muted-aa);
  margin:0.35rem 0 0}

/* ---- results: the collapsed shortlist map -------------------------------- */
.sl__mapWrap{margin:0 0 1rem}
.sl__mapToggle{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;
  font-size:0.75rem;color:var(--midnight);background:none;border:1px solid var(--line);
  border-radius:var(--radius);padding:0.6rem 1rem;min-height:40px;cursor:pointer;
  transition:border-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.sl__mapToggle:hover{border-color:var(--gold);color:var(--gold)}
.sl__mapWrap .sl__map{margin-top:0.75rem}

/* ---- the whole card is a link -------------------------------------------- */
/* The overlay anchor covers the card; every control that has its OWN target is
   raised above it, so VIEW FLOOR PLAN, WATCH VIDEO TOUR and the estimator link
   keep working and never trigger the card link. */
/* Same two layers the home cards already use for exactly this (.home__jump::after
   over .home__actions/.home__assets) — and from the --z-* scale, never raw
   numbers: build/audit_stacking.py fails the build on a bare z-index, which is
   how the old 100/140/170-vs-900/1200/1300 mess started. */
.sl__cardLink{position:absolute;inset:0;z-index:var(--z-local-raise);border-radius:inherit;
  text-indent:-9999px;overflow:hidden;white-space:nowrap}
.sl__cardLink:focus-visible{outline:2px solid var(--gold);outline-offset:-3px}
.sl__card:hover{border-color:var(--gold)}
.sl__cardActs,.sl__cardEst{position:relative;z-index:var(--z-local-over)}
.sl__cardActs .sl__plan{position:relative;z-index:var(--z-local-over)}
/* Flagged by its map pin. A ring, not a colour change — the card keeps reading
   the same, it just says "this one". */
.sl__card.is-flagged{border-color:var(--gold);box-shadow:0 0 0 2px rgba(var(--gold-soft-rgb),.45),var(--shadow)}
.sl__cardHoa{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.04em;color:var(--muted-aa);
  font-variant-numeric:tabular-nums;margin:0.15rem 0 0}

/* ---- the hero card's dark treatment for all of the above ------------------ */
.hsl .sl__pill{color:var(--ivory);background:rgba(var(--ivory-rgb),.06);
  border-color:rgba(var(--ivory-rgb),.26)}
.hsl .sl__pill:hover:not(:disabled){border-color:var(--gold-soft)}
.hsl .sl__pill.is-on{background:rgba(var(--gold-soft-rgb),.24);border-color:var(--gold-soft);color:var(--ivory)}
.hsl .sl__pill.is-some{border-color:var(--gold-soft);box-shadow:inset 0 0 0 1px var(--gold-soft)}
.hsl .sl__n{color:rgba(var(--ivory-rgb),.78);border-left-color:rgba(var(--ivory-rgb),.28)}
.hsl .sl__pickRow{margin:0 0 0.55rem}
.hsl .sl__pills{gap:0.3rem}
/* The hero panel is a 375px-wide glass card over a video, and the video is
   the thing that pays for the height: build/audit_resolution.py measures the
   <video> box against the 1920x1080 original, so every row this panel grows
   upscales a real asset a little further. Four pick rows fit only because
   they are tighter here than in the overlay. */
.hsl .sl__pill{padding:0.5rem 0.65rem;min-height:38px}
.hsl .sl__selCount{color:var(--ivory)}
@media(max-width:560px){
  .sl__map{height:clamp(220px,38vh,320px)}
}
.sl__moreWrap{margin:-0.75rem 0 1.5rem;text-align:center}
/* RESULTS "SHOW MORE LIKE THESE" — .sl__showMore, NOT .sl__more.
   It was .sl__more until 2026-08-01, and then step 1 grew a <details
   class="sl__more"> ("More filters") which shares the document with it: the
   homepage hero card renders step 1 while the overlay renders results, so both
   are mounted at once. Two consequences, both live:
     · this block sat AFTER the disclosure's at line ~2098 and overrode it, so
       the More-filters panel was being painted with the button's uppercase
       0.75rem/.14em type and 0.75rem 1.5rem padding;
     · build/audit_shortlist.py drives '.sl__more' to test 6 -> 12 pagination
       and always got the hero's disclosure instead, which is why it reported
       "'show more' revealed 6 cards, expected 12".
   build/audit_quiz_fold.py legitimately owns '.sl__more' for the disclosure,
   so the BUTTON is the one that moved. */
.sl__showMore{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;
  color:var(--midnight);background:none;border:1px solid var(--line);border-radius:var(--radius);
  padding:0.75rem 1.5rem;cursor:pointer;transition:border-color var(--dur-1) var(--ease)}
.sl__showMore:hover{border-color:var(--gold);color:var(--gold)}
.sl__refinePill,.sl__refScrim{display:none}
@media (max-width:640px){
  /* Bottom sheet. The results list stays on screen behind it — the whole point
     is watching the cards re-rank while you adjust. */
  .sl__refinePill{display:block;position:sticky;top:.4rem;z-index:var(--z-local-control);margin:0 auto 1rem;
    font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;
    color:var(--ivory);background:var(--midnight);border:1px solid var(--midnight);border-radius:99px;
    padding:0.75rem 1.5rem;min-height:44px;cursor:pointer;box-shadow:0 6px 18px -8px rgba(var(--midnight-rgb),.55)}
  .sl__refScrim{display:block;position:fixed;inset:0;z-index:var(--z-local-over);background:rgba(var(--midnight-rgb),.34);
    opacity:0;visibility:hidden;transition:opacity 200ms var(--ease),visibility 200ms}
  .sl__refScrim.is-on{opacity:1;visibility:visible}
  .sl__refine{position:fixed;left:0;right:0;bottom:0;top:auto;z-index:var(--z-local-control);
    max-height:72dvh;overflow-y:auto;-webkit-overflow-scrolling:touch;
    margin:0;border-radius:14px 14px 0 0;border-bottom:0;padding:1rem 1rem calc(1rem + env(safe-area-inset-bottom));
    box-shadow:0 -10px 34px -12px rgba(var(--midnight-rgb),.55);
    transform:translateY(101%);visibility:hidden;
    transition:transform 220ms var(--ease),visibility 220ms}
  .sl__refine.is-sheetOpen{transform:none;visibility:visible}
  .sl__refDone{display:inline-block;background:none;border:0;padding:0.25rem 0rem;margin:0;cursor:pointer;
    font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;color:var(--gold)}
  .sl__refLabel{flex:0 0 100%}
  .sl__chips--add{margin-left:0}
  .sl__stepVal{min-width:0;flex:1}
  @media (prefers-reduced-motion:reduce){
    .sl__refine,.sl__refScrim{transition:none}
  }
}
.sl__lead{background:var(--cream);border-radius:var(--radius);padding:1.5rem;margin-top:1rem}
.sl__leadTitle{font-family:'Cormorant Garamond',serif;font-size:1.5rem;font-weight:600;margin:0 0 1rem;color:var(--midnight)}
.sl__msg{font-size:0.875rem;color:var(--midnight);margin:0.75rem 0 0}
@media (max-width:900px){
  .sl{grid-template-columns:1fr;grid-template-rows:auto 1fr}
  .sl__aside{min-height:132px}
  .sl__asideInner{padding:1.5rem 1.5rem}
  .sl__asideTitle{font-size:1.5rem;margin-bottom:1rem}
  .sl__main{padding:1.5rem 1.5rem 3rem}
  .sl__opts--photo{grid-template-columns:1fr}
  .sl__optImg{aspect-ratio:16/7}
  .sl__card{grid-template-columns:116px 1fr;gap:0.75rem;padding:0.75rem 0 0.75rem 0.75rem}
  .sl__cardBody{padding:0 0.75rem 0 0}
}

/* =============================================================================
   SITEWIDE FILTERS — one bar, four page types (assets/filters.js).
   Sticky under the 74px header. Midnight/champagne, small-caps labels,
   chips scroll horizontally on phones rather than stacking into a wall.
   ========================================================================== */
/* filters.js hides cards with the `hidden` attribute; grid/flex parents would
   otherwise re-display them, so this has to win. */
[hidden]{display:none!important}

.flt{position:sticky;top:74px;z-index:var(--z-sticky-sub);margin:0 0 1.5rem}
.flt__toggle{display:none;width:100%;font-family:'Jost',sans-serif;text-transform:uppercase;
  letter-spacing:.16em;font-size:0.75rem;font-weight:500;padding:1rem 1.5rem;cursor:pointer;
  color:var(--midnight);background:var(--white);border:1px solid var(--midnight);border-radius:var(--radius)}
.flt.is-active .flt__toggle{background:var(--midnight);color:var(--ivory)}
/* Lot-size note: unresolved homes are shown at the END of a filtered list rather
   than hidden, and this says so. Deliberately quiet — it is an explanation, not a
   warning, and it must not compete with the result count beside it. */
/* Shortlist result card: lot size, and the positive match reason. The win line
   is gold because it is the answer to "why is this one here?" — the tradeoff line
   above it is the answer to "what's wrong with it", and the two must not look alike. */
.sl__cardLot{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.03em;color:var(--muted);margin:0.1rem 0 0}
.sl__win{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.03em;color:var(--gold);margin:0.15rem 0 0}
.sl__optSub{display:block;font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.06em;color:var(--muted);margin-top:.15rem}
.flt__lotnote{font-family:'Jost',sans-serif;font-size:0.75rem;line-height:1.5;
  letter-spacing:.02em;color:var(--muted);margin:0.35rem 0 0;max-width:62ch}
/* The unresolved tail reads as a distinct group without shouting. */
.home[data-unknown-lot] .home__site,.card[data-unknown-lot] .card__meta{opacity:.85}
/* ---- payment mode: the toggle and the loan-type control ----------------
   The mode box sits ABOVE .flt__inner and outside it, so it is never behind
   the phone-width "Filter & Sort" collapse. Payment-or-price is the question
   the list is answering; the facets are refinements to it, and hiding the
   question behind a control labelled "Filter" is what made the payment door
   invisible on phones the first time.
   .sl__tabs / .sl__tab are the QUIZ's classes, reused verbatim — see the
   comment on the toggle in assets/filters.js. Nothing is redefined here. */
.flt__modes{display:flex;flex-direction:column;gap:var(--sp-3);
  padding:var(--sp-4) var(--sp-5);margin-bottom:var(--sp-3);
  background:var(--white);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow)}
.flt__modes .sl__tabs{margin:0}
.flt__loan{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;min-width:0}
.flt__loan[hidden]{display:none}
/* Two lines in one pill: the program, and the down payment it assumes. The
   assumption is half of what the figure means, so it travels with the label
   rather than living in a legend somewhere else. */
.flt__pill--loan{flex-direction:column;align-items:flex-start;gap:1px;line-height:1.25}
.flt__sub{font-style:normal;font-size:0.625rem;letter-spacing:.06em;color:var(--muted-aa)}
.flt__pill--loan.is-on .flt__sub{color:inherit;opacity:.8}
@media (max-width:640px){
  .flt__modes{padding:var(--sp-3) var(--sp-4)}
  .flt__loan{gap:var(--sp-2)}
  .flt__loan .flt__pills{flex-wrap:wrap}
}
.flt__inner{display:flex;flex-wrap:wrap;align-items:center;gap:1rem 1.5rem;max-width:100%;
  padding:1rem 1.5rem;background:var(--white);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow)}
/* An off-mode facet group is hidden, not removed — its pills keep their
   listeners and their cached counts across a switch. */
.flt__group[hidden]{display:none}
.flt__group{display:flex;align-items:center;gap:0.5rem;min-width:0}
.flt__label{flex:none;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.16em;
  font-size:0.75rem;font-weight:500;color:var(--gold)}
/* WRAP, DO NOT SPILL. This row was display:flex with no flex-wrap, so it
   defaulted to nowrap and any row too wide for its container ran off the right
   edge instead of going to a second line. It only became visible when the VA
   loan pill was restored on 2026-08-02 and the filter bar grew: the payment
   band pills ended at 1181px inside a 1024px viewport. The mobile rule below
   (max-width:900px) deliberately scrolls horizontally instead, so it restates
   nowrap rather than inheriting this. build/audit_proportions.py asserts it. */
.flt__pills{display:flex;flex-wrap:wrap;gap:0.25rem;min-width:0}
.flt__pill{display:inline-flex;align-items:baseline;gap:0;flex:none;font-family:'Jost',sans-serif;
  font-size:0.75rem;letter-spacing:.04em;padding:0.5rem 0.75rem;cursor:pointer;color:var(--ink);
  background:transparent;border:1px solid var(--line);border-radius:var(--radius);
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease)}
.flt__pill:hover{border-color:var(--gold)}
.flt__pill.is-on{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}
/* an option that would return nothing is disabled, never hidden — a missing
   chip is more confusing than a greyed one (filters.js sets disabled to match) */
.flt__pill.is-void{opacity:.4}
.flt__pill:disabled{cursor:default}
/* THE COUNT IS METADATA, NOT PART OF THE VALUE. "2.5+ 163" read as one number;
   the hairline divider is what does the real work of separating them. Champagne
   at explicit alpha rather than element opacity, so the digits and the divider
   can brighten independently on the selected midnight background. The count
   spacing is owned here (pill gap is 0), so an empty count collapses cleanly. */
.flt__n{font-style:normal;font-size:0.78em;letter-spacing:.06em;font-variant-numeric:tabular-nums;
  color:rgba(var(--gold-soft-rgb),.55);margin-left:0.55rem;padding-left:0.55rem;
  border-left:1px solid rgba(var(--gold-soft-rgb),.22)}
.flt__n:empty{display:none}
.flt__pill.is-on .flt__n{color:rgba(var(--gold-soft-rgb),.75);border-left-color:rgba(var(--gold-soft-rgb),.35)}
/* Results pagination (2026-07-28). The size selector is chips like every other
   facet; the SHOW MORE button appends below the grid and never moves the page. */
.flt__pager{display:flex;flex-direction:column;align-items:center;gap:.6rem;margin:1.75rem 0 .5rem}
.flt__more{font-family:'Jost',sans-serif;font-size:0.8rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--midnight);background:transparent;border:1px solid var(--gold);border-radius:var(--radius);
  padding:0.85rem 2.2rem;min-height:44px;cursor:pointer;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.flt__more:hover{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}
.flt__pagerline{margin:0;font-family:'Jost',sans-serif;font-size:0.8rem;letter-spacing:.06em;color:var(--muted-aa);
  font-variant-numeric:tabular-nums}
@media (max-width:560px){
  .flt__more{width:100%;}
}
.flt__select{font-family:'Jost',sans-serif;font-size:0.75rem;padding:0.5rem 0.75rem;max-width:190px;
  /* a <select> won't shrink past its longest option without this, and that
     intrinsic width was dragging the whole mobile panel past the viewport */
  min-width:0;
  color:var(--ink);background:var(--ivory);border:1px solid var(--line);border-radius:var(--radius);cursor:pointer}
.flt__check{display:inline-flex;align-items:center;gap:0.5rem;font-size:0.75rem;color:var(--ink);cursor:pointer}
.flt__check input{accent-color:var(--gold)}
.flt__clear{margin-left:auto;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;
  font-size:0.75rem;color:var(--muted);background:none;border:none;cursor:pointer;
  text-decoration:underline;text-underline-offset:3px}
.flt__clear:hover{color:var(--gold)}
.flt__count{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.14em;font-size:0.75rem;
  color:var(--muted);margin:0 0 1.5rem;font-variant-numeric:tabular-nums}
.flt__empty{max-width:44ch;margin:2rem auto 3rem;text-align:center}
.flt__empty p{font-family:'Cormorant Garamond',Georgia,serif;font-size:1.5rem;line-height:1.4;
  color:var(--midnight);font-weight:500;text-wrap:balance}

@media (max-width:900px){
  .flt{top:0}
  .flt__toggle{display:block}
  .flt__inner{display:none;margin-top:0.5rem;flex-direction:column;align-items:stretch;gap:1rem;padding:1rem 1rem 1.5rem}
  .flt.is-open .flt__inner{display:flex}
  .flt__group{flex-direction:column;align-items:flex-start;gap:0.5rem;width:100%;min-width:0}
  .flt__group--check{flex-direction:row;align-items:center}
  /* chips scroll sideways instead of wrapping into a tall stack */
  .flt__pills{width:100%;min-width:0;flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;
    scrollbar-width:none;padding-bottom:0.25rem}
  .flt__pills::-webkit-scrollbar{display:none}
  .flt__select{max-width:none;width:100%}
  .flt__clear{margin-left:0;align-self:flex-start}
}

/* --- header phone: always reachable, every page --- */
.nav__tel{display:inline-flex;align-items:center;gap:.45rem;font-family:'Jost',sans-serif;
  font-size:.7rem;font-weight:400;letter-spacing:.12em;text-transform:uppercase;
  color:var(--gold-soft);white-space:nowrap;transition:color var(--dur-2) var(--ease)}
.nav__tel svg{width:15px;height:15px;flex:none}
.nav__tel:hover{color:var(--ivory)}
@media (max-width:900px){
  /* compact icon left of the hamburger — one tap to call from anywhere */
  /* .65rem, not .4rem: these are two 44px touch targets side by side and 6px
     between them is a mis-tap waiting to happen. It also keeps the header
     collision gate honest at an 8px floor instead of tuning the gate down to
     accommodate a spacing that was too tight anyway. */
  .nav__tel{margin-left:auto;margin-right:.65rem;width:44px;height:44px;justify-content:center;
    border:1px solid rgba(var(--gold-soft-rgb),.4);border-radius:50%}
  .nav__tel svg{width:17px;height:17px}
  .nav__telNum{display:none}
  body.mnav-open .nav__tel{display:none}   /* never competes with the open menu */
}

/* --- legal / privacy page --- */
.legal__body{max-width:760px;margin:0 auto}
.legal__body h3{font-family:'Cormorant Garamond',serif;font-size:1.5rem;font-weight:600;color:var(--midnight);
  margin:2rem 0 0.5rem}
.legal__body h3:first-child{margin-top:0}
.legal__body p{font-size:1rem;line-height:1.75;color:var(--muted);font-weight:300;margin:0 0 0.75rem}
.legal__body strong{color:var(--ink);font-weight:500}
.legal__body a{color:var(--midnight);border-bottom:1px solid var(--gold)}
.legal__contact{margin-top:2rem;padding-top:1.5rem;border-top:1px solid var(--line);font-size:0.875rem}

/* --- SMS consent (verbatim A2P wording; unchecked by default) --- */
.consent,.sl__consent{display:flex;align-items:flex-start;gap:0.5rem;margin:0.25rem 0 1rem;
  font-family:'Jost',sans-serif;font-size:0.75rem;line-height:1.55;font-weight:300;
  color:var(--muted);text-transform:none;letter-spacing:0;cursor:pointer}
.consent input,.sl__consent input{flex:none;width:17px;height:17px;margin-top:0.25rem;accent-color:var(--gold)}
.consent a,.sl__consent a{color:var(--midnight);border-bottom:1px solid var(--gold)}

/* =============================================================================
   ROYAL TREATMENT — global interaction polish.
   Everything here is cross-cutting: focus, selection, scrollbars, pressed
   states, page transitions, image loading. Component-specific polish stays
   with its component.
   ========================================================================== */

/* --- Focus: keep the ring for keyboards, lose the browser blue ----------- */
:focus{outline:none}
:focus-visible{outline:2px solid var(--gold);outline-offset:3px;border-radius:var(--radius)}
/* champagne needs its lighter tone to stay visible on midnight grounds */
.nav :focus-visible,.mnav :focus-visible,.hero :focus-visible,.page-hero :focus-visible,
.footer :focus-visible,.cta-band :focus-visible,.hsl :focus-visible,
.visit :focus-visible,.mobile-callbar :focus-visible{outline-color:var(--gold-soft)}

/* --- Selection ----------------------------------------------------------- */
::selection{background:rgba(var(--gold-rgb),.26);color:var(--midnight)}

/* --- Scrollbar: desktop pointers only; phones keep the native overlay ----- */
@media (hover:hover) and (pointer:fine){
  html{scrollbar-width:thin;scrollbar-color:rgba(var(--gold-rgb),.42) transparent}
  ::-webkit-scrollbar{width:11px;height:11px}
  ::-webkit-scrollbar-track{background:transparent}
  ::-webkit-scrollbar-thumb{background:rgba(var(--gold-rgb),.38);border:3px solid var(--ivory);
    border-radius:var(--radius-pill);background-clip:padding-box}
  ::-webkit-scrollbar-thumb:hover{background:rgba(var(--gold-rgb),.68);background-clip:padding-box}
}

/* --- Pressed state: touch gets no hover, so it needs this ---------------- */
.btn:active,.flt__pill:active,.sl__opt:active,.home__broc:active,.fp-dlall:active,
.flt__clear:active,.sl__btn:active,.visit__submit:active{transform:translateY(1px)}

/* --- Hover: gentle lift on cards, arrow nudge on links ------------------- */
@media (hover:hover) and (pointer:fine){
  .card,.home,.plan{transition:transform var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease)}
  .card:hover,.home:hover,.plan:hover{transform:translateY(-3px);box-shadow:var(--shadow-lift)}
  .link-more:hover .arw{transform:translateX(5px)}
}

/* --- Page transition: fade out on leave so navigation never white-flashes.
   The colour has to live on <html>, not <body>, or the gap between documents
   paints white. But once <html> has its own background, <body>'s stops
   propagating to the canvas and becomes a real painted box — which then covers
   every negative-z-index layer on the page (the hero video/stills at z:-2 and
   the hero overlay at z:-1 both vanished behind it). So <body> goes
   transparent and <html> owns the page colour outright. */
html{background:var(--ivory)}
body{background:transparent;transition:opacity var(--dur-1) var(--ease)}
html.is-leaving body{opacity:0}
@media (prefers-reduced-motion:reduce){
  html.is-leaving body{opacity:1}
}

/* --- Images: fade + unblur as they decode, over a warm tint. Never a grey
   box popping in. `is-ready` is set by script.js on load (or immediately for
   images already in cache). --------------------------------------------- */
@media (prefers-reduced-motion:no-preference){
  img.blurup{opacity:0;filter:blur(14px);transform:scale(1.02);
    transition:opacity var(--dur-3) var(--ease),filter var(--dur-3) var(--ease),
               transform var(--dur-3) var(--ease)}
  img.blurup.is-ready{opacity:1;filter:none;transform:none}
}
.card__media,.home__media,.plan__media,.page-hero__img{background-color:var(--cream)}

/* =============================================================================
   SCHEDULE A VISIT — modal. Replaces every CTA that used to anchor-scroll to
   the footer form. Bottom-sheet on phones, centred panel on desktop.
   ========================================================================== */
.visit{position:fixed;inset:0;z-index:var(--z-modal);display:flex;align-items:center;justify-content:center;
  padding:1.5rem;opacity:0;visibility:hidden;
  transition:opacity var(--dur-2) var(--ease),visibility var(--dur-2)}
.visit.is-open{opacity:1;visibility:visible}
.visit__scrim{position:absolute;inset:0;background:rgba(var(--midnight-rgb),.72);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
/* THE PANEL ITSELF NEVER SCROLLS — its BODY does.
   It used to be the scroll container with .visit__x absolutely positioned
   inside it, which meant the close button scrolled away with the form: on a
   short viewport you could scroll the consent text into view and lose the X
   entirely. Same failure .sl fixed by anchoring its close button outside the
   scroll container. Here the panel is a flex column, .visit__form/.visit__done
   take the scrolling, and the X stays pinned to a panel edge that no longer
   moves. `overflow:hidden` also clips content to the border radius, so the
   top edge reads as a clean panel edge instead of a translucent band with the
   page showing through behind it. */
.visit__panel{position:relative;width:100%;max-width:480px;max-height:calc(100dvh - 3rem);
  display:flex;flex-direction:column;overflow:hidden;background:var(--ivory);
  border-radius:var(--radius);box-shadow:var(--shadow-modal);padding:2rem 2rem 2rem;
  transform:translateY(12px) scale(.985);
  transition:transform var(--dur-2) var(--ease)}
/* min-height:0 is what actually lets a flex child scroll — without it the
   child's content sets the floor and the panel grows past max-height. */
.visit__form,.visit__done{overflow-y:auto;-webkit-overflow-scrolling:touch;min-height:0}
.visit.is-open .visit__panel{transform:none}
.visit__x{position:absolute;top:.6rem;right:.8rem;width:44px;height:44px;background:none;border:none;
  font-size:2rem;line-height:1;color:var(--muted);cursor:pointer;transition:color var(--dur-1) var(--ease)}
.visit__x:hover{color:var(--midnight)}
.visit__eyebrow{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.28em;
  font-size:0.625rem;font-weight:500;color:var(--gold);margin:0}
.visit__title{font-family:'Cormorant Garamond',Georgia,serif;font-size:2rem;font-weight:600;
  line-height:1.12;color:var(--midnight);margin:0.75rem 0 0.5rem;text-wrap:balance}
.visit__sub{font-size:0.875rem;font-weight:300;line-height:1.6;color:var(--muted);margin:0 0 1.5rem}
.visit__field{display:block;margin-bottom:1rem}
.visit__field > span{display:block;font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);margin-bottom:0.5rem}
.visit__field input,.visit__field select{width:100%;padding:0.75rem 1rem;font-family:'Jost',sans-serif;
  font-size:16px;color:var(--ink);background:var(--white);border:1px solid var(--line);
  border-radius:var(--radius);transition:border-color var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease)}
.visit__field input:focus,.visit__field select:focus{outline:none;border-color:var(--gold);
  box-shadow:0 0 0 3px rgba(var(--gold-rgb),.14)}
/* gentle validation — a champagne note, never a red shout */
.visit__field.is-off input,.visit__field.is-off select{border-color:var(--gold)}
.visit__note{display:block;font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.04em;
  color:var(--gold);margin-top:0.25rem;min-height:1em}
.visit__row{display:grid;grid-template-columns:1fr 1fr;gap:0.75rem}
.visit__consent{display:flex;gap:0.5rem;align-items:flex-start;margin:0.25rem 0 1rem;
  font-size:0.75rem;line-height:1.55;color:var(--muted);cursor:pointer}
.visit__consent input{margin-top:0.25rem;accent-color:var(--gold);flex:none}
.visit__consent a{color:var(--gold);text-decoration:underline;text-underline-offset:2px}
.visit__submit{width:100%;font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.18em;
  font-size:0.75rem;font-weight:500;padding:1rem 1.5rem;cursor:pointer;color:var(--ivory);
  background:var(--midnight);border:1px solid var(--midnight);border-radius:var(--radius);
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),opacity var(--dur-1) var(--ease)}
.visit__submit:hover{background:var(--gold);border-color:var(--gold);color:var(--midnight)}
.visit__submit[disabled]{opacity:.6;cursor:default}
.visit__done{text-align:center;padding:1rem 0 0.5rem}
.visit__done p{font-family:'Cormorant Garamond',Georgia,serif;font-size:1.5rem;line-height:1.35;
  color:var(--midnight);font-weight:500;text-wrap:balance}
.visit__fine{font-size:0.75rem;color:var(--muted);margin-top:1rem;line-height:1.5}
body.visit-open{overflow:hidden}

@media (max-width:560px){
  /* bottom sheet */
  .visit{padding:0;align-items:flex-end}
  .visit__panel{max-width:none;border-radius:var(--radius) var(--radius) 0 0;
    max-height:92dvh;padding:2rem 1.5rem 1.5rem;transform:translateY(26px)}
  .visit__row{grid-template-columns:1fr}
}
@media (prefers-reduced-motion:reduce){
  /* every overlay, not just the modal — the audit caught .sl and .mnav missing */
  .visit,.visit__panel,.reveal,.sl,.mnav,.bv{transition-duration:1ms!important}
  .visit__panel{transform:none}
  .mnav{transform:none}
  /* The hero is NOT handled here, deliberately. Hiding .hero__video would hide
     its poster with it, and the poster is the reduced-motion hero — a finished
     2560x1440 still, not a hole. script.js is what enforces this: it never
     attaches a source under reduced motion, and pauses the video if the
     preference is turned on mid-session. One URL, one request, no rotation. */
}

/* --- Nothing floats over a full-screen surface ----------------------------
   The layer scale already puts every modal (--z-modal) above the chat launcher
   (--z-chat-launcher) and the header (--z-sticky-header), so none of this is
   load-bearing for STACKING any more. It stays for a different reason: a
   launcher that is merely behind a modal is still a tab stop and still reads
   to a screen reader, so it is removed from the page outright while a modal
   owns the screen. */
body.visit-open .tgchat-launch,
body.visit-open .tgchat-panel,
body.visit-open .mobile-callbar,
body.sl-open .tgchat-launch,
body.sl-open .tgchat-panel,
body.sl-open .mobile-callbar,
body.bv-open .tgchat-launch,
body.bv-open .tgchat-panel,
body.bv-open .mobile-callbar,
body.lb-open .tgchat-launch,
body.lb-open .tgchat-panel,
body.lb-open .mobile-callbar{display:none!important}

/* --- The header yields to any modal --------------------------------------
   Stacking alone stops the header PAINTING over a dialog. It does not stop the
   header swallowing a click, receiving focus, or being announced — the nav is
   still a live landmark sitting behind a scrim the user cannot see through.
   While a modal owns the screen the header is inert: no hit-testing, no tab
   stops. `inert` is set on .nav by the modal open/close helpers in JS for AT;
   this is the pointer half, which needs no JS and cannot get out of sync.
   The mobile menu is deliberately absent: it IS header chrome, spawned by the
   nav toggle, so disabling the header would strand its own opener. */
body.visit-open .nav,
body.sl-open .nav,
body.bv-open .nav,
body.lb-open .nav{pointer-events:none}

/* Schedule a Visit inside the mobile menu — styled as a menu row, not a button,
   so it reads as part of the list. Added because hiding the hero's secondary
   CTAs left the visit modal with no reachable trigger on a phone. */
.mnav__visit{display:flex;align-items:center;min-height:48px;padding:.5rem 0;width:100%;
  background:none;border:none;cursor:pointer;text-align:left;
  font-family:'Cormorant Garamond',Georgia,serif;font-size:1.95rem;font-weight:500;
  line-height:1.15;color:var(--ivory);letter-spacing:.01em}
.mnav__visit:active{color:var(--gold-soft)}
@media (max-width:380px){ .mnav__visit{font-size:1.7rem;min-height:46px} }

/* =================================================================
   /map — full area map. Desktop-primary; phones get list-over-map.
   ================================================================= */
.am-wrap{max-width:var(--max);margin:0 auto}
.am-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:0.5rem;margin:0 0 1rem}
.am-toolbar__label{font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.16em;
  font-size:0.75rem;color:var(--muted);margin-right:0.25rem}
.am-chip{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.04em;padding:0.5rem 0.75rem;
  border:1px solid var(--line);border-radius:var(--radius-pill);background:transparent;color:var(--ink);
  cursor:pointer;white-space:nowrap;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease)}
.am-chip:hover{border-color:var(--gold)}
.am-chip.is-on{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}
.am-chip--rt.is-on{background:var(--redtag);border-color:var(--redtag)}
.am-clear{background:none;border:0;font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted);cursor:pointer;text-decoration:underline;padding:0.5rem 0.25rem}
.am-count{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gold);margin-left:auto}

/* map + list side by side on desktop; stacked (map first, short) on phones */
.am-grid{display:grid;grid-template-columns:1.55fr 1fr;gap:1.5rem;align-items:start}
.am-grid > *{min-width:0}
#area-map{height:min(74dvh,720px);border-radius:var(--radius);border:1px solid var(--line);
  box-shadow:var(--shadow);background:var(--cream)}
.am-side{max-height:min(74dvh,720px);overflow:auto;border:1px solid var(--line);
  border-radius:var(--radius);background:var(--white)}
.am-list{list-style:none;margin:0;padding:0}
.am-row{display:flex;align-items:center;gap:0.75rem;padding:0.75rem 1rem;border-bottom:1px solid var(--line);
  cursor:pointer;transition:background var(--dur-1) var(--ease)}
.am-row:last-child{border-bottom:0}
.am-row:hover{background:var(--ivory)}
.am-row__swatch{width:9px;height:9px;border-radius:50%;flex:0 0 auto}
.am-row__main{display:flex;flex-direction:column;gap:0.25rem;min-width:0;flex:1}
.am-row__name{font-family:'Cormorant Garamond',serif;font-size:1rem;font-weight:600;
  color:var(--midnight);text-decoration:none}
.am-row__name:hover{color:var(--gold)}
.am-row__meta{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.05em;color:var(--muted)}
.am-row__price{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.04em;color:var(--ink);
  white-space:nowrap}
.am-row__rt{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--redtag);border:1px solid var(--redtag);border-radius:var(--radius-pill);padding:0rem 0.5rem;
  white-space:nowrap}
.am-empty{padding:1.5rem 1rem;font-size:0.875rem;line-height:1.7;color:var(--muted)}

/* layer toggles */
.am-layers{display:flex;flex-wrap:wrap;gap:1rem;margin:1rem 0 0;padding:1rem 0 0;
  border-top:1px solid var(--line)}
.am-layers label{display:inline-flex;align-items:center;gap:0.5rem;font-family:'Jost',sans-serif;
  font-size:0.75rem;letter-spacing:.06em;color:var(--ink);cursor:pointer}
.am-layers input{accent-color:var(--gold)}

/* legend */
.am-legend{display:flex;flex-wrap:wrap;gap:1rem;margin:1rem 0 0;font-family:'Jost',sans-serif;
  font-size:0.625rem;letter-spacing:.06em;color:var(--muted)}
.am-legend span{display:inline-flex;align-items:center;gap:0.5rem}
.am-legend i{width:9px;height:9px;border-radius:50%;display:inline-block}

/* --- markers ------------------------------------------------------------- */
.am-pin{background:none;border:0}
.am-pin__dot{display:block;width:16px;height:16px;border-radius:50%;border:2px solid var(--white);
  box-shadow:0 2px 6px rgba(var(--midnight-rgb),.35);margin:6px}
.am-pin--rt .am-pin__rt{position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;
  background:var(--redtag);border:1.5px solid var(--white)}
.am-lm{background:none;border:0}
.am-lm__dot{display:block;width:10px;height:10px;border-radius:2px;background:var(--gold);
  border:1.5px solid var(--white);transform:rotate(45deg);box-shadow:0 1px 4px rgba(var(--midnight-rgb),.3)}
.am-ref{background:none;border:0}
.am-ref__dot{display:block;width:10px;height:10px;border-radius:50%;background:transparent;
  border:2px dashed var(--midnight);opacity:.7}

/* --- popup card ---------------------------------------------------------- */
.am-popup .leaflet-popup-content-wrapper{border-radius:var(--radius);padding:0;overflow:hidden;
  box-shadow:0 10px 30px rgba(var(--midnight-rgb),.28)}
.am-popup .leaflet-popup-content{margin:0;width:240px!important}
.am-card__img{display:block;width:100%;height:120px;object-fit:cover}
.am-card__img--ph{background:var(--midnight)}
.am-card__body{padding:0.75rem 1rem 1rem}
.am-card__rt{display:inline-block;font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--redtag);border:1px solid var(--redtag);
  border-radius:var(--radius-pill);padding:0rem 0.5rem;margin-bottom:0.25rem}
.am-card__name{font-family:'Cormorant Garamond',serif;font-size:1.25rem;font-weight:600;
  color:var(--midnight);margin:0 0 0.25rem}
.am-card__loc{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);margin:0 0 0.5rem}
.am-card__price{font-family:'Jost',sans-serif;font-size:0.75rem;color:var(--ink);margin:0 0 0rem}
.am-card__count{font-family:'Jost',sans-serif;font-size:0.625rem;color:var(--muted);margin:0 0 0.5rem}
.am-card__link{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gold);text-decoration:none}
.am-card__link:hover{text-decoration:underline}

/* --- phones: list carries the page, map becomes a short locator band ------ */
@media (max-width:900px){
  .am-grid{grid-template-columns:1fr}
  #area-map{height:44dvh;min-height:300px}
  .am-side{max-height:none;overflow:visible}
  .am-count{margin-left:0;width:100%}
}
@media (max-width:560px){
  #area-map{height:38dvh;min-height:250px}
  .am-toolbar{gap:0.5rem}
  .am-chip{font-size:0.75rem;padding:0.5rem 0.75rem}
}

/* =================================================================
   /discover-ocala — the area story
   ================================================================= */
.dsc-wrap{max-width:var(--max);margin:0 auto;display:grid;gap:4rem}
.dsc{display:grid;grid-template-columns:1fr 1fr;gap:3rem;align-items:center}
.dsc > *{min-width:0}
.dsc:nth-child(even) .dsc__media{order:2}
.dsc__media{position:relative;border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow);aspect-ratio:4/3;
  background:var(--cream)}
.dsc__media img{width:100%;height:100%;object-fit:cover;display:block}
/* Flagged placeholder — reads as intentional, names the shot required. */
.dsc__media--ph{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:1rem;padding:2rem;text-align:center;background:var(--midnight);
  border:1px solid var(--gold-soft);box-shadow:none}
.dsc__phtag{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--gold);border:1px solid var(--gold);border-radius:var(--radius-pill);padding:0.25rem 0.75rem}
.dsc__phnote{font-family:'Jost',sans-serif;font-size:0.75rem;line-height:1.6;
  color:rgba(var(--ivory-rgb),.6);margin:0;max-width:30ch}
.dsc__title{font-family:'Cormorant Garamond',serif;font-size:2rem;font-weight:600;
  color:var(--midnight);line-height:1.15;margin:0.25rem 0 1rem}
.dsc__copy p{font-size:1rem;line-height:1.85;margin:0 0 1rem;color:var(--ink)}
.dsc__copy p:last-child{margin-bottom:0}

/* Location math grid */
.lm{max-width:820px;margin:0 auto}
.lm__grid{border-top:1px solid var(--line)}
.lm__row{display:grid;grid-template-columns:1.1fr .9fr 1.4fr;gap:1rem;align-items:baseline;
  padding:1rem 0.25rem;border-bottom:1px solid var(--line)}
.lm__place{font-family:'Cormorant Garamond',serif;font-size:1.25rem;font-weight:600;color:var(--midnight)}
.lm__time{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--gold)}
.lm__note{font-family:'Jost',sans-serif;font-size:0.875rem;color:var(--muted);line-height:1.6}
.lm__kicker{font-family:'Cormorant Garamond',serif;font-size:1.5rem;font-weight:600;line-height:1.45;
  color:var(--midnight);margin:2rem 0 1rem;text-align:center}

/* Closing bridge */
.dsc-bridge{max-width:680px;margin:0 auto;text-align:center}
.dsc-bridge__title{font-family:'Cormorant Garamond',serif;font-size:2rem;font-weight:600;
  color:var(--midnight);margin:0 0 1rem}
.dsc-bridge p{font-size:1rem;line-height:1.85;color:var(--ink);margin:0 0 1.5rem}
.dsc-bridge__btns{display:flex;gap:0.75rem;justify-content:center;flex-wrap:wrap}
.dsc-bridge__agents{font-size:0.875rem;color:var(--muted);margin-top:2rem}

/* Community-page cross-link band */
.xlink__inner{max-width:var(--max);margin:0 auto;display:flex;align-items:center;
  justify-content:space-between;gap:2rem;flex-wrap:wrap}
.xlink__copy{flex:1 1 340px;min-width:0}
.xlink__title{font-family:'Cormorant Garamond',serif;font-size:1.5rem;font-weight:600;
  color:var(--midnight);margin:0.25rem 0 0.5rem}
.xlink__copy p{font-size:0.875rem;line-height:1.75;color:var(--ink);margin:0;max-width:52ch}
.xlink__btns{display:flex;gap:0.75rem;flex-wrap:wrap}

@media (max-width:900px){
  .dsc{grid-template-columns:1fr;gap:1.5rem}
  .dsc:nth-child(even) .dsc__media{order:0}
  .dsc-wrap{gap:3rem}
  .lm__row{grid-template-columns:1fr auto;row-gap:0.25rem}
  .lm__note{grid-column:1 / -1;font-size:0.75rem}
  .xlink__inner{flex-direction:column;align-items:flex-start}
}
@media (max-width:560px){
  .dsc__title{font-size:1.5rem}
  .lm__kicker{font-size:1.25rem}
  .dsc-bridge__btns .btn{width:100%}
}

/* =================================================================
   /partners — hook-first order: sticky section nav + commission band
   ================================================================= */
.pnav{position:sticky;top:74px;z-index:var(--z-sticky-sub);background:rgba(var(--midnight-rgb),.96);backdrop-filter:blur(10px);
  border-bottom:1px solid rgba(var(--gold-soft-rgb),.22)}
.pnav__inner{max-width:var(--max);margin:0 auto;display:flex;align-items:center;gap:1.4rem;
  padding:.75rem 2rem;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}
.pnav__inner::-webkit-scrollbar{display:none}
.pnav a{font-family:'Jost',sans-serif;font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(var(--ivory-rgb),.72);text-decoration:none;white-space:nowrap;
  transition:color var(--dur-2) var(--ease)}
.pnav a:hover{color:var(--gold-soft)}
.pnav__cta{color:var(--midnight)!important;background:var(--gold);padding:.42rem .9rem;
  border-radius:var(--radius-pill);margin-left:auto}
.pnav__cta:hover{background:var(--gold-soft);color:var(--midnight)!important}
.pnav__vcf{border:1px solid rgba(var(--gold-soft-rgb),.45);padding:.4rem .8rem;border-radius:var(--radius-pill)}

.comm__inner{max-width:900px;margin:0 auto;text-align:center}
.comm__title{font-family:'Cormorant Garamond',serif;font-size:2rem;font-weight:600;
  color:var(--midnight);margin:0.25rem 0 0.5rem;line-height:1.1}
.comm__big{font-size:clamp(2rem,4.2vw,3.75rem);color:var(--gold);display:inline-block;line-height:1}
.comm__sub{font-size:1rem;line-height:1.8;color:var(--ink);max-width:60ch;margin:0 auto 2rem}
.comm__ladder{display:flex;align-items:flex-end;justify-content:center;gap:1rem;margin:0 0 2rem}
.comm__step{flex:1 1 0;min-width:0;background:var(--white);border:1px solid var(--line);
  border-radius:var(--radius);padding:1rem 0.75rem;box-shadow:var(--shadow);
  display:flex;flex-direction:column;gap:0.25rem;justify-content:flex-end}
.comm__step--s{padding-top:1rem}
.comm__step--m{padding-top:2rem}
.comm__step--l{padding-top:3rem;border-color:var(--gold);box-shadow:var(--shadow-lift)}
.comm__step b{font-family:'Cormorant Garamond',serif;font-size:2rem;font-weight:600;color:var(--midnight)}
.comm__step--l b{color:var(--gold)}
.comm__step span{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted)}
.comm__actions{display:flex;gap:0.75rem;justify-content:center;flex-wrap:wrap;margin-bottom:1.5rem}
.comm__terms{max-width:70ch;margin:0 auto;text-align:left}

@media (max-width:760px){
  .pnav{top:64px}
  .pnav__inner{padding:.7rem 1.2rem;gap:1.1rem}
  .pnav__cta{margin-left:0}
  .comm__big{font-size:2.75rem}
  .comm__ladder{gap:0.5rem}
  .comm__step{padding:1rem 0.5rem}
  .comm__step--m,.comm__step--l{padding-top:1.5rem}
  .comm__step b{font-size:1.5rem}
  .comm__step span{font-size:0.75rem;letter-spacing:.06em}
}

/* ===== C4: estimator rate control (merged from build; see docs) ===== */
/* ============================================================
   Payment Estimator — interest-rate control (slider + typed field + promo chip)
   Merge into styles.css near the other .est__ rules (~line 883, right after
   `.est__field input[type=range]{width:100%;accent-color:var(--gold)}`).
   Nothing here overrides an existing selector except that one width:100%,
   which must become flex-shrinkable inside .est__rate-row.
   ============================================================ */

.est__field--rate{gap:0.75rem}

/* Row: slider takes the slack, the number box is intrinsically sized.
   min-width:0 on BOTH is what keeps #estimator from gaining a min-content
   wider than a 375px phone (see the .btn--full note above — same class of bug). */
.est__rate-row{display:flex;align-items:center;gap:0.75rem;min-width:0}
.est__rate-row input[type=range]{flex:1 1 0;min-width:0;width:auto;margin:0}

/* Typed rate box — reads as one control; the wrapper carries the border so the
   trailing % sits inside it. */
.est__rate-num{
  flex:0 0 auto;display:inline-flex;align-items:baseline;gap:0rem;
  padding:0.5rem 0.5rem;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--ivory);
  transition:border-color var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease);
}
/* NOTE the [type=text] — it is load-bearing. The existing
   `.est__field input[type=text]` rule (0,2,1) also matches this input and would
   otherwise win on font-size/padding/border/background and draw a second box
   inside the wrapper. Matching its specificity + coming later is what wins. */
.est__rate-num input[type=text]{
  width:3.1rem;padding:0;border:0;border-radius:0;background:transparent;
  font-family:'Cormorant Garamond',serif;font-size:1.25rem;font-weight:600;
  line-height:1.1;color:var(--midnight);text-align:right;
}
.est__rate-num input[type=text]:focus{outline:none}
.est__rate-num b{
  font-family:'Jost',sans-serif;font-size:0.75rem;font-weight:500;
  letter-spacing:.06em;color:var(--gold);
}
.est__rate-num:focus-within{
  border-color:var(--gold);
  box-shadow:0 0 0 2px rgba(var(--gold-rgb),.20);
}

/* Promo reset chip. Hidden by default in the markup; the inline #est-rate-gate
   script un-hides it before first paint only while the promo window is open,
   and estimator.js re-hides it if that gate is missing. */
.est__chip{
  justify-self:start;
  display:inline-flex;align-items:center;gap:0.5rem;
  font-family:'Jost',sans-serif;text-transform:uppercase;letter-spacing:.12em;
  font-size:0.75rem;font-weight:500;line-height:1;
  padding:0.5rem 0.75rem;
  border:1px solid var(--gold);border-radius:var(--radius-pill,999px);
  background:transparent;color:var(--gold);cursor:pointer;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),
             border-color var(--dur-1) var(--ease);
}
.est__chip::before{
  content:"";width:5px;height:5px;border-radius:50%;
  background:currentColor;opacity:.75;flex:0 0 auto;
}
.est__chip:hover{background:var(--gold);color:var(--white,var(--white));border-color:var(--gold)}
.est__chip.is-on{background:var(--midnight);color:var(--gold-soft);border-color:var(--midnight)}
.est__chip[hidden]{display:none}

/* On phones the inputs card is only ~197px of content box. Side by side that
   left the slider 105px for a 3.00–9.00 range (~0.9px per 0.05 step, measured).
   Wrapping gives the slider the full width and parks the typed box above-right. */
@media (max-width:560px){
  .est__rate-row{flex-wrap:wrap}
  .est__rate-row input[type=range]{order:2;flex:1 1 100%}
  .est__rate-num{order:1;margin-left:auto}
}

@media (prefers-reduced-motion:reduce){
  .est__rate-num,.est__chip{transition:none}
}

/* ------------------------------------------------------------------
   OPTIONAL — pre-existing bug, NOT part of the rate-control work.
   Merge it or drop it; nothing above depends on it.

   #est-price is a bare <input type=text> with no width, so it keeps its
   default ~20-character intrinsic width: measured 242px inside a 144px
   content box at a 320px viewport. #estimator's scrollWidth is 331 vs a
   clientWidth of 320 there — same class of clipped-content bug as the
   568px .btn--full one, and it is already live. It is invisible at 375+
   (263px of content box, so 242 fits) and it reproduces with the entire
   new rate field display:none, so it predates this change.
   Scoped to the id on purpose: the obvious `.est__field input[type=text]`
   also matches #est-rate-num and, sitting later in the file at equal
   specificity, stretches the rate box to 189px. Do not "simplify" it.
   ------------------------------------------------------------------ */
#est-price{width:100%}

/* Shortlist: price-step note + the estimator bridge on result cards.
   The link is the ONLY payment-adjacent thing in the quiz — it carries a price
   to the estimator and nothing else. No rate, APR or monthly figure is rendered
   anywhere in the wizard. */
.sl__note{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.06em;
  color:var(--muted-aa);margin:0.75rem 0 0}
.hsl .sl__note{color:rgba(var(--ivory-rgb),.92)}
.sl__cardEst{margin:0.25rem 0 0.25rem}
.sl__cardEst a{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.06em;
  color:var(--gold);text-decoration:none;border-bottom:1px solid rgba(var(--gold-rgb),.45);
  padding-bottom:1px;transition:color var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease)}
.sl__cardEst a:hover{color:var(--gold-soft);border-color:var(--gold-soft)}
.hsl .sl__cardEst a{color:var(--gold-soft);border-color:rgba(var(--gold-soft-rgb),.5)}
.sl__cardEst a:focus-visible{outline:2px solid var(--gold);outline-offset:3px}

/* =============================================================================
   /PARTNERS — RESOURCE QUICK-ACCESS BAR + MINI MAP
   Sits directly under the page hero. Deliberately NOT sticky: .pnav already
   covers mid-scroll access, and two stacked sticky bars eats a phone screen.
   Champagne small-caps triggers over midnight dropdown panels.
   NOTE: the 640px sheet breakpoint is duplicated in assets/quickaccess.js.
   ========================================================================== */
.qab{background:var(--midnight);border-bottom:1px solid rgba(var(--gold-soft-rgb),.22)}
.qab__inner{max-width:var(--max);margin:0 auto;padding:1.5rem 1.5rem 2rem;
  display:grid;grid-template-columns:1fr 280px;gap:1.5rem 2rem;align-items:start}
.qab__col{grid-column:1}
.qab__eyebrow{font-family:'Jost',sans-serif;font-size:0.625rem;letter-spacing:.24em;
  text-transform:uppercase;color:var(--gold-soft);margin:0 0 0rem}
.qab__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:0.75rem}
/* Grid stretches the ITEM, but the trigger inside it was content-height, so a
   one-line label sat 14px shorter than its wrapping neighbours (measured at
   1440px: "Plan Brochures" 48px vs 62px for the other three). Stretch the
   trigger to the row height so all four share one baseline at every width. */
.qab__item{position:relative;display:flex}
.qab__trigger{display:flex;align-items:center;justify-content:space-between;gap:0.5rem;width:100%;
  height:100%;
  min-height:48px;padding:0.75rem 1rem;cursor:pointer;text-align:left;
  font-family:'Jost',sans-serif;font-size:0.75rem;font-weight:500;letter-spacing:.16em;
  text-transform:uppercase;color:var(--gold-soft);
  background:rgba(var(--ivory-rgb),.04);border:1px solid rgba(var(--gold-soft-rgb),.34);border-radius:var(--radius);
  transition:border-color var(--dur-1) var(--ease),background var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.qab__trigger:hover,.qab__trigger:focus-visible{border-color:var(--gold);color:var(--ivory);
  background:rgba(var(--gold-soft-rgb),.12)}
.qab__caret{width:15px;height:15px;flex:0 0 15px;transition:transform var(--dur-1) var(--ease)}
.qab__trigger[aria-expanded="true"]{border-color:var(--gold);color:var(--ivory);background:rgba(var(--gold-soft-rgb),.14)}
.qab__trigger[aria-expanded="true"] .qab__caret{transform:rotate(180deg)}
.qab__panel{position:absolute;z-index:var(--z-dropdown);top:calc(100% + .45rem);left:0;min-width:100%;width:max-content;max-width:min(92vw,520px);
  max-height:min(58dvh,420px);overflow-y:auto;-webkit-overflow-scrolling:touch;
  background:linear-gradient(168deg,var(--midnight),var(--midnight-2));border:1px solid rgba(var(--gold-soft-rgb),.34);
  border-radius:var(--radius);padding:0.75rem;box-shadow:0 22px 46px -20px rgba(var(--black-rgb),.75);
  animation:qabIn 170ms var(--ease)}
@keyframes qabIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
.qab__sheetBar{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  padding:0rem 0.25rem 0.5rem}
.qab__sheetTitle{font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--gold-soft);margin:0}
.qab__sheetClose{display:none}
.qab__list{list-style:none;margin:0;padding:0}
.qab__list--cols{columns:2;column-gap:1rem;min-width:23rem}
/* The two right-hand tiles open leftwards; a 520px panel hung off the
   left edge of the 4th column would run past the viewport. */
.qab__item:nth-child(3) .qab__panel,
.qab__item:nth-child(4) .qab__panel{left:auto;right:0}
.qab__list--cols li{break-inside:avoid}
.qab__link{display:block;width:100%;text-align:left;background:none;border:0;border-radius:4px;
  padding:0.5rem 0.5rem;cursor:pointer;font-family:'Jost',sans-serif;font-size:0.875rem;
  color:rgba(var(--ivory-rgb),.86);text-decoration:none;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.qab__link:hover,.qab__link:focus-visible{background:rgba(var(--gold-soft-rgb),.16);color:var(--ivory)}
.qab__link--zip,.qab__link--anchor{margin-top:0.25rem;color:var(--gold-soft);
  border-top:1px solid rgba(var(--gold-soft-rgb),.24);border-radius:0;padding-top:0.5rem}
.qab__none{margin:0.25rem 0.5rem;font-size:0.875rem;color:rgba(var(--ivory-rgb),.7)}
/* mini map — static SVG, links through to the full Leaflet map */
.qab__map{grid-column:2;display:block;position:relative;border-radius:var(--radius);
  overflow:hidden;border:1px solid rgba(var(--gold-soft-rgb),.45);text-decoration:none;
  transition:border-color var(--dur-2) var(--ease),transform var(--dur-2) var(--ease)}
.qab__map:hover{border-color:var(--gold);transform:translateY(-2px)}
.qab__map img{display:block;width:100%;height:auto;aspect-ratio:4/3;object-fit:cover}
.qab__mapLabel{position:absolute;left:0;right:0;top:0;padding:0.75rem 1rem 1rem;
  font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ivory);background:linear-gradient(to bottom,rgba(var(--midnight-rgb),.92),rgba(var(--midnight-rgb),0))}
.qab__scrim{display:none}
@media (max-width:900px){
  .qab__inner{grid-template-columns:1fr}
  .qab__map{grid-column:1}
}
@media (max-width:640px){
  /* 2x2 tappable grid; each tile opens a bottom sheet with the page behind it. */
  .qab__inner{padding:1rem 1rem 1.5rem;gap:1rem}
  .qab__grid{grid-template-columns:1fr 1fr;gap:0.5rem}
  .qab__trigger{min-height:60px;font-size:0.75rem;letter-spacing:.12em;padding:0.75rem 0.75rem}
  /* width:auto is load-bearing: the desktop panel is width:max-content, which
     beats left:0/right:0 and pushed the sheet (and its Done button) off the
     right edge of a 375px screen. The two-column min-width goes with it. */
  .qab__panel{position:fixed;z-index:var(--z-dropdown);left:0;right:0;bottom:0;top:auto;
    width:auto;min-width:0;max-width:none;max-height:72dvh;border-radius:14px 14px 0 0;border-bottom:0;
    padding:1rem 1rem calc(1rem + env(safe-area-inset-bottom));
    box-shadow:0 -12px 38px -12px rgba(var(--black-rgb),.8);animation:qabSheetIn 200ms var(--ease)}
  @keyframes qabSheetIn{from{transform:translateY(101%)}to{transform:none}}
  .qab__sheetBar{padding:0rem 0 0.75rem;border-bottom:1px solid rgba(var(--gold-soft-rgb),.2);margin-bottom:0.5rem}
  .qab__sheetClose{display:inline-block;background:none;border:0;padding:0.25rem;cursor:pointer;
    font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.14em;text-transform:uppercase;color:var(--gold)}
  .qab__scrim{display:block;position:fixed;inset:0;z-index:calc(var(--z-dropdown) - 1);background:rgba(var(--midnight-rgb),.5)}
  body.qab-sheet{overflow:hidden}
  .qab__list--cols{columns:1;min-width:0}
  .qab__link{padding:0.75rem 0.5rem;font-size:0.875rem}
}
@media (prefers-reduced-motion:reduce){
  .qab__panel{animation:none}
}

/* Long-label buttons (e.g. "Download All Inventory Sheets (ZIP)") can't fit
   one line at .75rem on a 375 screen once .14-.2em tracking is added — the
   tracking alone was ~79px. Tighten tracking+padding under 400px so they stay
   one line at the AA-floor size, no wrap, no overflow. */
@media(max-width:400px){
  .btn{letter-spacing:.05em;padding-left:1rem;padding-right:1rem}
}

/* NOTE ON PLACEMENT: this block lives at the END of the file deliberately.
   It was first inserted near the top, where later component rules of equal
   specificity (.flt__select's 12px font, .hcar__dot's padding:0) silently
   overrode it — the fixes were present but inert. An override layer has to
   come last. Do not move it back up. */
/* ===========================================================================
   iOS SAFARI HARDENING
   Added in the iOS polish pass. Every rule here fixes a WebKit-specific
   behaviour that Blink does not share, so none of it is visible on desktop
   Chrome — which is exactly why these went unnoticed.
   =========================================================================== */

/* --- 1. INPUT AUTO-ZOOM ---------------------------------------------------
   Mobile Safari zooms the whole page when a focused form control's font-size is
   under 16px, and does NOT zoom back out on blur. That is the "it opens weird
   and stays zoomed" report. There is no global input font rule in this
   stylesheet, so any control a component does not size explicitly inherits the
   UA default (~13.3px) and triggers it.
   16px is the floor, applied at mobile widths only so the desktop type scale is
   untouched. Sizes ABOVE 16px are left alone (the estimator's 24px price field
   is deliberate). */
@media (max-width:767px){
  input,select,textarea,
  .flt__select,.fp-controls select,.pc-paste-row input,
  .est__pills button,.est__rate-num input[type=text]{
    font-size:16px;
  }
  /* Checkboxes have no text, so the 16px floor is irrelevant to zoom — but a
     17px hit area is under the 44px minimum. Grow the touch target without
     moving the box: padding on the label row does the work. */
  .consent,.sl__consent,.visit__consent{min-height:44px}
  .consent input,.sl__consent input,.visit__consent input{width:22px;height:22px}
  /* Same touch-target floor in the chat panel. NOT folded into the rule above:
     that one sets min-height on the whole label row, and the chat's row lives
     in a fixed-height panel where the composer must stay on screen with the
     keyboard up — so the box grows and the row does not. */
  .tgchat-consent input{width:22px;height:22px}
}

/* --- 2. SAFE AREAS ------------------------------------------------------
   iPhones with a home indicator put ~34px of non-tappable screen below the
   fold. A fixed bottom bar without safe-area padding sits underneath it: the
   bar is visible but its bottom half cannot be tapped. Two sheets already had
   this; every other fixed element did not. */
.mobile-callbar{padding-bottom:env(safe-area-inset-bottom)}
@media (max-width:900px){
  .pbar{padding-bottom:env(safe-area-inset-bottom)}
  /* NOTE: the launcher offset is NOT set here. An earlier version of this block
     set `bottom:calc(1.5rem + env(safe-area-inset-bottom))`, which — because this
     block is the override layer at the end of the file — silently replaced the
     existing `calc(var(--callbar-h) + 12px)` and dropped the launcher from 68px
     to ~58px, on top of a sticky bar that this same block had just grown to
     ~90px. The launcher's clearance is now computed in one place; see
     "STICKY-BAR CLEARANCE" at the end of this file. */
  .mnav{padding-bottom:env(safe-area-inset-bottom);
        padding-left:env(safe-area-inset-left);padding-right:env(safe-area-inset-right)}
  .visit__panel{padding-bottom:calc(1.5rem + env(safe-area-inset-bottom))}
  .sl{padding-bottom:env(safe-area-inset-bottom)}
}

/* --- 3. SCROLL CHAINING -------------------------------------------------
   Without overscroll-behavior:contain, a swipe that reaches the end of a
   modal's scroll area continues into the page behind it — the background moves
   under an open overlay. The JS lock (assets/ios-scrolllock.js) stops the body
   scrolling at all; this stops the chain reaching it in the first place, which
   also kills Safari's rubber-band bounce inside the sheet. */
.visit,.visit__panel,.sl,.bv,.mnav,.lightbox,.qab__panel{overscroll-behavior:contain}

/* --- 4. TAP TARGETS ----------------------------------------------------
   Apple's minimum is 44x44pt. The carousel dots were 7px — technically
   clickable, realistically not. The dot stays 7px VISUALLY; the button around
   it grows via padding, so the row looks identical and the target is 44px.
   background-clip:content-box keeps the added padding transparent. */
/* Gated on WIDTH, not (hover:none). Both describe roughly the same population
   here, but width is what the rest of this stylesheet keys on and what can
   actually be verified in a headless harness — a hover-gated rule silently did
   nothing when tested, which is how the 7px dots survived the first pass. */
@media (max-width:767px){
  /* CAROUSEL DOTS — the button is the TAP TARGET, a pseudo-element is the DOT.
     The previous attempt kept the 7px box and grew it with padding +
     background-clip:content-box. That failed on device: `.hcar__dot.is-on`
     sets `background:` as a SHORTHAND, which resets background-clip to
     border-box, and at (0,2,0) it outranks this (0,1,0) rule — so the active
     dot painted its full 45px box gold and scale(1.25) took it to 56px. That
     is the "huge gold circle" over the image.
     Separating the concerns makes it unbreakable: the <button> is a 44px
     transparent hit area with NO background of its own, and ::after draws the
     8px dot. A shorthand on the button can no longer repaint the dot. */
  .hcar__dot{width:44px;height:44px;padding:0;box-sizing:border-box;
             background:none !important;border-radius:0;transform:none !important;
             display:grid;place-items:center}
  .hcar__dot::after{content:"";display:block;width:8px;height:8px;border-radius:50%;
             background:rgba(var(--ivory-rgb),.62);
             transition:background var(--dur-2) var(--ease),transform var(--dur-2) var(--ease)}
  .hcar__dot.is-on::after{background:var(--gold);transform:scale(1.25)}
  .hcar__dots{gap:0;bottom:0;right:0}
  /* ARROWS ARE DESKTOP-ONLY. (hover:none) alone did not gate them — it computed
     to display:block at 390px — so gate on width too, which is deterministic
     and testable. Touch users swipe. */
  .hcar__arw{display:none !important}
  .sl__stepBtn{width:44px;height:44px;flex:0 0 44px}
  .sl__dot{height:4px}
  .qab__sheetClose,.mnav__close,.bv__close{min-width:44px;min-height:44px}
}

/* ===========================================================================
   /partners buyer-style search  +  homepage realtor band
   =========================================================================== */

/* --- mode toggle. Two equal controls; neither is a "more" affordance. ------ */
.pmode{display:flex;gap:.5rem;justify-content:center;margin:0 0 2rem;flex-wrap:wrap}
.pmode__btn{font-family:'Jost',sans-serif;font-size:.8rem;letter-spacing:.12em;
  text-transform:uppercase;padding:.85rem 1.4rem;min-height:44px;cursor:pointer;
  background:transparent;color:var(--ink);border:1px solid var(--line);border-radius:2px;
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),
             border-color var(--dur-1) var(--ease)}
.pmode__btn:hover{border-color:var(--gold)}
.pmode__btn.is-on{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}
.pmode__note{text-align:center;max-width:620px;margin:0 auto 1.5rem}

/* --- community strip: name / from / count, into the BUYER community page --- */
.cstrip{margin-top:3rem;padding-top:2rem;border-top:1px solid var(--line)}
.cstrip__lead{text-align:center;color:var(--muted);font-size:.92rem;margin-bottom:1.25rem}
.cstrip__row{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:.6rem}
.cstrip__item{display:grid;grid-template-columns:1fr auto;gap:.1rem .75rem;align-items:baseline;
  padding:.85rem 1rem;min-height:44px;text-decoration:none;color:inherit;
  border:1px solid var(--line);border-radius:2px;background:var(--ivory);
  transition:border-color var(--dur-1) var(--ease),transform var(--dur-1) var(--ease)}
.cstrip__item:hover{border-color:var(--gold);transform:translateY(-1px)}
.cstrip__name{font-weight:500;letter-spacing:.01em}
.cstrip__from{color:var(--gold);font-size:.85rem;white-space:nowrap}
.cstrip__n{grid-column:1/-1;color:var(--muted);font-size:.8rem;letter-spacing:.06em;
  text-transform:uppercase}

/* --- homepage realtor band ------------------------------------------------
   Full-bleed midnight, centred, one CTA. Deliberately NOT a banner: same type
   scale and champagne rule as every other section head, so it reads as part of
   the page rather than an ad dropped into it. */
.rband{max-width:none;background:var(--midnight);color:var(--ivory);
  padding-left:0;padding-right:0;text-align:center}
.rband__inner{max-width:var(--max);margin:0 auto;padding:0 2rem;
  display:flex;flex-direction:column;align-items:center}
.rband__eyebrow{color:var(--gold-soft)}
.rband__rule{display:block;width:54px;height:1px;background:var(--gold);margin:1.25rem auto 1.5rem}
.rband__title{font-size:clamp(1.9rem,4vw,2.7rem);font-weight:500;color:var(--ivory);
  max-width:760px;line-height:1.14}
.rband__value{margin-top:1.1rem;color:rgba(var(--ivory-rgb),.86);font-weight:300;
  font-size:1.02rem;letter-spacing:.02em;max-width:620px}
.rband__cta{margin-top:2rem}



@media (max-width:767px){
  /* 375px: the hero link drops BELOW the CTA rather than beside it, so it can
     never crowd the primary button or push it off-line. */
  .rband__inner{padding:0 1.5rem}
  .cstrip__row{grid-template-columns:1fr}
  .pmode{gap:.4rem}
  .pmode__btn{flex:1 1 auto;padding:.85rem .9rem;font-size:.72rem}
}

/* ===========================================================================
   MARKET LANDING PAGES (/new-homes-*)  +  Discover communities-by-area
   =========================================================================== */

/* Live inventory stat row. Numbers come from the workbook at build, so this is
   the one element on the page that must never look like marketing garnish. */
.mstat{padding-top:2.5rem;padding-bottom:2.5rem}
.mstat__row{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  background:rgba(var(--midnight-rgb),.10);border:1px solid rgba(var(--midnight-rgb),.10)}
.mstat__i{background:var(--ivory);padding:1.4rem 1rem;text-align:center}
.mstat__i b{display:block;font-family:'Cormorant Garamond',serif;font-size:clamp(1.8rem,3.4vw,2.5rem);
  font-weight:600;line-height:1;color:var(--midnight)}
.mstat__i span{display:block;margin-top:.45rem;color:var(--muted);font-size:.78rem;
  letter-spacing:.10em;text-transform:uppercase}
.mstat__note{margin-top:1rem;text-align:center;color:var(--muted);font-size:.88rem}

/* FAQ. <details> so it works with no JS and each answer is crawlable text. */
.mfaq{max-width:820px;margin:0 auto}
.mfaq__item{border-bottom:1px solid var(--line);padding:1.1rem 0}
.mfaq__item summary{cursor:pointer;font-weight:500;letter-spacing:.01em;
  list-style:none;display:flex;justify-content:space-between;gap:1rem;min-height:32px;
  align-items:center}
.mfaq__item summary::-webkit-details-marker{display:none}
.mfaq__item summary::after{content:"+";color:var(--gold);font-size:1.3rem;line-height:1;flex:none}
.mfaq__item[open] summary::after{content:"\2013"}
.mfaq__item p{margin-top:.85rem;color:var(--ink);font-weight:300;line-height:1.6}

/* Discover: communities grouped by area */
.dcom__area{margin-bottom:2.5rem}
.dcom__h{font-family:'Jost',sans-serif;font-size:.8rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--gold);margin-bottom:.9rem}

/* Home detail up-links — the link mesh, styled as a quiet trailing line. */
.hd__up{margin-top:1.6rem;text-align:center;color:var(--muted);font-size:.9rem;
  line-height:1.9}
.hd__up a{color:var(--midnight);border-bottom:1px solid rgba(var(--gold-rgb),.5)}
.hd__up a:hover{color:var(--gold)}

@media (max-width:767px){
  .mstat__row{grid-template-columns:repeat(2,1fr)}
  .mstat__i{padding:1.1rem .75rem}
}

/* Community xlink button row: allow wrapping. A third button landed here (the
   market landing page) and "New homes in the Nature Coast" is wider than a
   375px viewport allows on one line with its siblings. The short labels fix the
   width; this makes the row resilient to the next label that grows. */
@media (max-width:767px){
  .xlink__btns{flex-wrap:wrap}
  .xlink__btns .btn{white-space:normal;text-align:center}
}

/* iOS SLIDE BLEED.
   .hcar__track moves with translate3d. WebKit lets a 3D-transformed child paint
   outside a parent that clips with overflow:hidden + border-radius, so the next
   slide shows along the right edge mid-swipe. Chrome does not reproduce it, so
   this cannot be verified here — it is the standard WebKit mitigation: a mask
   forces a real clip, and isolation keeps the transformed track in the parent's
   own stacking context. Harmless everywhere else. */
.hcar{-webkit-mask-image:-webkit-radial-gradient(white,black);
      mask-image:radial-gradient(white,black);
      isolation:isolate;overflow:hidden}
.hcar__track{will-change:transform;backface-visibility:hidden}
/* Slides must be exactly the container width — no flex-basis rounding drift. */
.hcar__slide{flex:0 0 100%;width:100%;max-width:100%;min-width:100%}

/* ===========================================================================
   NAV "REALTOR PARTNERS" PILL — the agent door.
   Replaces the hero text link.

   THE SHIMMER IS A BACKGROUND, NOT AN ELEMENT.
   First attempt used an absolutely-positioned ::after sweeping from left:-60%
   to left:120%, clipped with overflow:hidden. That failed the header gate on 80
   of 192 route/width combinations: a child parked past the right edge inflates
   the pill's scrollWidth, and the gate reads scrollWidth > clientWidth as
   "label truncated". An animated background-position moves no box at all, so
   the pill's geometry is identical at every frame.

   THE PULSE IS A GLOW, NOT A SCALE.
   The brief asked for "soft glow scale 1.0 -> 1.03 -> 1.0". A transform is
   excluded from layout but NOT from getBoundingClientRect, so a 1.03 scale on a
   ~150px pill grows it ~4.5px and eats the header's 16px minimum gaps — the
   same gate, a different rule. A box-shadow bloom reads as the intended "gold
   catching light" and cannot move a neighbour by a single pixel.

   One sweep per 6s (~1s of travel, 5s still). One arrival bloom, never repeated.
   prefers-reduced-motion gets a plain static gold pill.
   =========================================================================== */
.nav__partner{
  background-image:linear-gradient(100deg,
    rgba(255,250,240,0) 38%,
    rgba(255,250,240,.30) 50%,
    rgba(255,250,240,0) 62%);
  background-repeat:no-repeat;
  background-size:180% 100%;
  background-position:-140% 0;
  animation:pillShimmer 6s ease-in-out 1.6s infinite,
            pillArrive 1200ms var(--ease) 400ms 1 both;
}
@keyframes pillShimmer{
  0%   {background-position:-140% 0}
  18%  {background-position:240% 0}   /* ~1.1s of travel … */
  100% {background-position:240% 0}   /* … then it waits out the cycle */
}
@keyframes pillArrive{
  0%   {box-shadow:0 0 0 0 rgba(var(--gold-soft-rgb),0)}
  40%  {box-shadow:0 0 18px 3px rgba(var(--gold-soft-rgb),.45)}
  100% {box-shadow:0 0 0 0 rgba(var(--gold-soft-rgb),0)}
}
.nav__partner:hover{animation:none}
@media (prefers-reduced-motion:reduce){
  .nav__partner,.nav__partner::before{animation:none!important}
  .nav__partner{background-image:none}
}

/* ===========================================================================
   STICKY-BAR CLEARANCE — the chat launcher must never sit on a sticky bar.
   ONE place computes this, because it has now been got wrong twice: first
   against the Call/Text bar, then against /partners' REGISTER/PROGRAMS/
   INVENTORY quick-nav (whose gold "Text" cell is the "stray gold rectangle"
   showing under the launcher — it is not stray, it is being covered).

   clearance = bar height + safe-area inset + 12px

   The safe-area term is essential: both bars carry
   padding-bottom:env(safe-area-inset-bottom), so on a notched iPhone a 56px bar
   occupies ~90px and a launcher offset that ignores the inset lands on top of it.
   z-index stays on the token scale (--z-chat-launcher) — no ad-hoc values.
   =========================================================================== */
:root{ --pbar-h:56px; }   /* .pbar__btn min-height — keep in sync */

@media (max-width:640px){
  /* default: pages with the Call/Text bar */
  .tgchat-launch{
    bottom:calc(var(--callbar-h) + env(safe-area-inset-bottom) + 12px);
    z-index:var(--z-chat-launcher);
  }
  .tgchat-panel{
    bottom:calc(var(--callbar-h) + env(safe-area-inset-bottom) + 12px);
    max-height:calc(100dvh - var(--callbar-h) - env(safe-area-inset-bottom) - 2.5rem);
  }
  /* /partners hides the Call/Text bar and shows .pbar instead */
  body.partners .tgchat-launch{
    bottom:calc(var(--pbar-h) + env(safe-area-inset-bottom) + 12px);
  }
  body.partners .tgchat-panel{
    bottom:calc(var(--pbar-h) + env(safe-area-inset-bottom) + 12px);
    max-height:calc(100dvh - var(--pbar-h) - env(safe-area-inset-bottom) - 2.5rem);
  }
  /* THE TEASER RIDES THE SAME SAFE-AREA MATH AS THE LAUNCHER. These are the
     authoritative bottom values (the earlier 640px block does not know about
     the inset), so the teaser is re-stated here rather than left to inherit a
     value that stops short of the home indicator. */
  .tgchat-teaser{
    bottom:calc(var(--callbar-h) + env(safe-area-inset-bottom) + 12px + 58px);
  }
  body.partners .tgchat-teaser{
    bottom:calc(var(--pbar-h) + env(safe-area-inset-bottom) + 12px + 58px);
  }
}
/* Between 641 and 900px neither bar is shown, so only the inset matters. */
@media (min-width:641px) and (max-width:900px){
  .tgchat-launch{bottom:calc(1.5rem + env(safe-area-inset-bottom))}
  .tgchat-teaser{bottom:calc(1.5rem + env(safe-area-inset-bottom) + 58px)}
}

/* =============================================================================
   FIND YOUR HOME — payment door (/find-your-home.html)
   Dark behind PAYMENT_SEARCH_ENABLED; the CSS ships either way, which costs
   nothing and means flipping the flag is a one-line change with no restyling.

   NEITHER DOOR IS THE FAVOURED ONE. The two tabs share a width, a weight, a
   type size, a border and a state treatment. There is no "recommended" chip,
   no accent on one, no ordering signal beyond left-to-right. If you are about
   to make one tab heavier, that is a compliance decision, not a design one.

   Every z-index here comes from the --z-* scale (audit_stacking.py enforces it).
   ========================================================================== */
.fyh__tabs{display:flex;gap:0;margin:0 0 2rem;border-bottom:1px solid var(--line)}
.fyh__tab{flex:1 1 0;min-width:0;font-family:'Jost',sans-serif;font-weight:500;
  text-transform:uppercase;letter-spacing:.16em;font-size:0.8125rem;
  padding:1.125rem 1rem;cursor:pointer;color:var(--muted-aa);background:transparent;
  border:0;border-bottom:2px solid transparent;margin-bottom:-1px;
  transition:color var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease)}
.fyh__tab:hover{color:var(--midnight)}
.fyh__tab.is-on{color:var(--midnight);border-bottom-color:var(--gold)}

/* The not-a-lender line. Persistent and legible — never fine print. */
.fyh__standing{max-width:70ch;margin:0 0 2rem;font-size:0.875rem;line-height:1.7;
  color:var(--ink);border-left:2px solid var(--gold);padding-left:1rem}

/* ---- PAYMENT RANGE — two handles over one track --------------------------
   Two stacked native range inputs. The track and fill are painted by the
   wrapper; the inputs themselves are transparent and sit on top so each handle
   stays a real, focusable, keyboard-steppable control. pointer-events are off
   on the input bodies and back ON for the thumbs, so a click between the
   handles does not jump whichever input happens to be on top. */
.fyh__range{background:var(--white);border:1px solid var(--line);
  border-radius:var(--radius);padding:1.4rem 1.5rem;margin:0 0 1.5rem}
.fyh__slider{position:relative;height:2.4rem;margin:.9rem 0 .2rem}
.fyh__track{position:absolute;top:50%;left:0;right:0;height:4px;margin-top:-2px;
  background:var(--line);border-radius:2px}
.fyh__track-fill{position:absolute;top:0;bottom:0;background:var(--gold);border-radius:2px}
.fyh__slider input[type=range]{position:absolute;top:0;left:0;width:100%;height:100%;
  margin:0;background:none;-webkit-appearance:none;appearance:none;pointer-events:none}
.fyh__slider input[type=range]:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.fyh__slider input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
  pointer-events:auto;width:22px;height:22px;border-radius:50%;background:var(--white);
  border:2px solid var(--gold);box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:pointer}
.fyh__slider input[type=range]::-moz-range-thumb{pointer-events:auto;width:22px;height:22px;
  border-radius:50%;background:var(--white);border:2px solid var(--gold);
  box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:pointer}
.fyh__slider input[type=range]::-moz-range-track{background:none;border:none}
.fyh__count{margin:.4rem 0 0;font-family:'Jost',sans-serif;font-size:.95rem;color:var(--ink)}
.fyh__nearest{margin:.6rem 0 0;font-size:.9rem;color:var(--muted-aa);line-height:1.7}
.fyh__nearest-btn{font-family:'Jost',sans-serif;font-size:.85rem;font-weight:500;
  color:var(--ink);background:var(--white);border:1px solid var(--gold);
  border-radius:var(--radius);padding:.42rem .85rem;cursor:pointer;
  transition:background var(--dur-2) var(--ease)}
.fyh__nearest-btn:hover{background:var(--gold);color:var(--white)}

/* ---- REG Z DISCLOSURE ----------------------------------------------------
   Adjacent to the results, never collapsed, never a footer. A stated monthly
   payment is a triggering term, so this block is part of the payment, not a
   note about it. Do not add display:none, <details>, or a "show more". */
/* The wrapper reg_z_block() emits. Inherits .section's max-width and its
   symmetric 2rem horizontal gutter — that gutter is the whole point, since
   without it the block's own padding overran the content box. Vertical padding
   is dropped so the disclosure sits tight under the payment it qualifies. */
.regz-sec{padding-top:0;padding-bottom:0}
.regz{margin:0 0 1.5rem;padding:1rem 1.15rem;border:1px solid var(--line);
  border-left:3px solid var(--gold);border-radius:var(--radius);background:var(--cream)}
.regz__terms{margin:0;font-family:'Jost',sans-serif;font-size:.85rem;line-height:1.7;color:var(--ink)}
.regz__terms:empty{display:none}
.regz__standing{margin:.5rem 0 0;font-size:.8rem;line-height:1.7;color:var(--muted-aa)}
.regz__eho{margin-left:.35rem}
/* THE NOTE RATE AND THE APR — EQUAL, AND PLAIN.
   1026.24(c) permits a dwelling-secured ad to state a simple annual rate
   beside the APR only "in conjunction with, but not more conspicuously than"
   the annual percentage rate. EQUAL is what the rule asks for; BOLD was never
   part of it. These figures shipped bold on 2026-08-02 and were unbolded the
   same day so the card has one focal point — the payment — rather than three
   competing ones.
   What has not changed, and is the part that actually enforces the rule: both
   figures share ONE class. Everything is inherit, so there is no declaration
   here that can raise the rate above the APR without raising the APR with it.
   Rate louder than APR is not a styling mistake this file can express.
   font-size and color inherit deliberately — this rule is used inside
   .regz__terms, .pay__disc, .home__payterms, .sl__cardTerms and the dark .hsl
   variants, which set different sizes and colours, and the figures must track
   whatever their own container uses. white-space guards the token: "APR" split
   from its number is a different claim (build/audit_token_integrity.py). */
.regz__eq{font-weight:inherit;font-size:inherit;color:inherit;white-space:nowrap}

.fyh__gate{display:grid;gap:1.5rem;margin:0 0 1.5rem}
@media (min-width:900px){.fyh__gate{grid-template-columns:repeat(3,1fr);gap:2rem}}
.fyh__step{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);
  padding:1.5rem;transition:opacity var(--dur-2) var(--ease)}
/* A locked step is dimmed but never hidden: the shape of the gate should be
   visible from the first paint so nobody wonders what else is coming. */
.fyh__step.is-locked{opacity:.45}
.fyh__step.is-locked button,.fyh__step.is-locked input{pointer-events:none}
.fyh__stepn{font-family:'Jost',sans-serif;font-size:0.6875rem;text-transform:uppercase;
  letter-spacing:.18em;color:var(--gold);margin:0 0 0.5rem}
.fyh__steph{font-family:'Cormorant Garamond',serif;font-size:1.375rem;font-weight:600;
  color:var(--midnight);margin:0 0 0.75rem}
.fyh__steph--sub{font-size:1.125rem;margin-top:1.25rem}
.fyh__steph b{font-style:normal;font-variant-numeric:tabular-nums;color:var(--gold)}
.fyh__pills{display:flex;flex-wrap:wrap;gap:0.5rem}
.fyh__pill{display:inline-flex;align-items:center;justify-content:center;
  font-family:'Jost',sans-serif;font-size:0.8125rem;letter-spacing:.04em;
  min-height:44px;padding:0.625rem 1rem;cursor:pointer;color:var(--ink);
  background:transparent;border:1px solid var(--line);border-radius:var(--radius);
  transition:background var(--dur-1) var(--ease),color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease)}
.fyh__pill:hover{border-color:var(--gold)}
.fyh__pill.is-on{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}
/* FHA and Conventional are the same size on purpose — see the header comment. */
.fyh__pill--wide{flex:1 1 0;min-width:0}
.fyh__aside{margin:1rem 0 0;font-size:0.8125rem;line-height:1.7;color:var(--muted-aa)}
.fyh__aside a{color:var(--ink);border-bottom:1px solid var(--gold)}
.fyh__field{display:block;margin:1rem 0 0;font-size:0.8125rem;color:var(--muted-aa)}
.fyh__field>span{display:block;margin-bottom:0.375rem}
.fyh__numwrap{display:inline-flex;align-items:center;gap:0.25rem;border:1px solid var(--line);
  border-radius:var(--radius);padding:0 0.75rem;background:var(--white)}
.fyh__numwrap input{width:4.5rem;min-height:44px;border:0;background:transparent;
  font-family:'Jost',sans-serif;font-size:1rem;color:var(--midnight);
  font-variant-numeric:tabular-nums}
.fyh__numwrap input:focus{outline:none}
.fyh__numwrap b{font-weight:400;color:var(--muted-aa)}
.fyh__hint{margin:0.75rem 0 0;font-size:0.8125rem;line-height:1.6;color:var(--muted-aa)}
.fyh__msg{margin:0.5rem 0 0;font-size:0.8125rem;color:var(--midnight);min-height:1.2em}
.fyh__rate-row{display:flex;align-items:center;gap:1rem;margin-top:1rem;flex-wrap:wrap}
.fyh__rate-row input[type=range]{flex:1 1 10rem;min-width:0;min-height:44px;accent-color:var(--gold)}
/* Until the visitor moves it, the slider reads as unset rather than as a value
   we chose for them. There is no default rate in this feature. */
.fyh__rate-row input[type=range]{opacity:.55}
.fyh__rate-row input[type=range].is-set{opacity:1}

.fyh__await{margin:0 0 1.5rem;font-size:0.9375rem;line-height:1.7;color:var(--muted-aa);
  border-top:1px solid var(--line);padding-top:1.5rem}
.fyh__assume{margin:0 0 1.5rem;border-top:1px solid var(--line);padding-top:1.5rem}
.fyh__assume-line{margin:0;font-family:'Jost',sans-serif;font-size:0.875rem;
  letter-spacing:.04em;color:var(--midnight)}
.fyh__assume-prices{margin:0.375rem 0 0;font-size:0.8125rem;color:var(--muted-aa)}
.fyh__incentive{margin:0 0 1.5rem;font-size:0.875rem;line-height:1.7;color:var(--ink)}
.fyh__entry{margin:0 0 1.5rem;font-size:0.9375rem;line-height:1.7}
.fyh__entry a{color:var(--midnight);border-bottom:1px solid var(--gold)}
.fyh__entry-note{display:block;font-size:0.8125rem;color:var(--muted-aa)}

/* ---------------------------------------------------------------------------
   THE PAYMENT DOOR'S TWO PANES — sticky map left, results scrolling right.

   The map used to sit above the grid, which made it useless for its only job:
   you scroll to a card, and by then the map that would tell you where it is
   has left the screen. So it gets its own column and stays put while the list
   moves past it.

   POSITION:STICKY, NOT FIXED. Fixed would take the map out of flow and it
   would hang over the footer and the CTA band at the end of the list. Sticky
   keeps it inside its column: it pins while the column is on screen and
   releases at the bottom of it, which is the behaviour anyone actually wants.
   top:74px clears the sticky site header, matching .flt and .pnav.

   The map column is FIRST in the DOM as well as first visually, so keyboard
   and screen-reader order match what is on screen. The toggle button lives at
   the top of the pane and is display:none above the breakpoint — on desktop
   there is nothing to toggle, the map is simply there.
   --------------------------------------------------------------------------- */
.fyh__two{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,9fr);gap:2rem;align-items:start}
.fyh__listPane{min-width:0}
.fyh__mapPane{min-width:0}
.fyh__mapSticky{position:sticky;top:74px}
.fyh__map{height:calc(100vh - 74px - 5.5rem);min-height:360px;max-height:760px;
  width:100%;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--paper,#f4f2ee);overflow:hidden}
/* Leaflet writes its own z-index stack — it ships 400-700 on its panes — so the
   whole thing is clamped here, under the site header and any modal, or a pin
   renders over the nav.
   THROUGH THE TOKEN, NOT A LITERAL. This used to be a bare numeric literal —
   the same value, but bypassing the --z-* scale, and build/audit_stacking.py
   fails the build on exactly that: a raw number is how the layer drift it was
   written to stop gets reintroduced one innocuous declaration at a time.
   --z-local-raise carries that value, and its stated meaning — "content above
   its own decoration", scoped inside a component — is precisely what these
   panes are doing within .fyh__map's own stacking context.
   (Do not write the offending property/number pair in a comment here: the gate
   scans the stylesheet as text and does not strip comments, so prose naming it
   literally fails the build just as the declaration would.) */
.fyh__map .leaflet-pane,.fyh__map .leaflet-top,.fyh__map .leaflet-bottom{z-index:var(--z-local-raise)}
.fyh__mapNote{margin:0.55rem 0 0;font-family:'Jost',sans-serif;font-size:0.75rem;
  letter-spacing:.04em;line-height:1.6;color:var(--muted-aa);min-height:1.2em}
.fyh__pinNote{margin:0.35rem 0 0;font-size:0.75rem;line-height:1.5;color:var(--muted-aa)}
.cm-card__link{display:block;color:var(--midnight);border-bottom:1px solid var(--gold)}
.fyh__mapToggle{display:none}

/* The right column is ~9/16 of the content width, so three cards would be
   ~230px each — narrower than the card's own photo aspect wants. Two columns
   inside the pane, dropping to one when the column itself gets tight. */
.fyh__listPane .grid--3{grid-template-columns:repeat(2,1fr);gap:1.5rem}
@media (max-width:1180px){
  .fyh__two{grid-template-columns:minmax(0,6fr) minmax(0,8fr);gap:1.5rem}
  .fyh__listPane .grid--3{grid-template-columns:1fr}
}

/* ---- below the breakpoint: one column, map behind a toggle ----------------
   A sticky map on a phone would eat half the viewport permanently to explain
   a list the visitor can already read. It collapses to a button, closed by
   default, and when opened it is a fixed-height block ABOVE the results
   rather than a sticky one — on a small screen "always visible" and "enough
   room for the cards" cannot both be true, and the cards win. */
@media (max-width:899px){
  .fyh__two{display:block}
  .fyh__mapPane{margin:0 0 1.5rem}
  .fyh__mapSticky{position:static}
  .fyh__mapToggle{display:block;width:100%;min-height:44px;cursor:pointer;
    font-family:'Jost',sans-serif;font-size:0.75rem;letter-spacing:.16em;text-transform:uppercase;
    color:var(--ink);background:transparent;border:1px solid var(--line);
    border-radius:var(--radius);padding:0.75rem 1rem}
  .fyh__mapToggle:hover{border-color:var(--gold)}
  .fyh__mapToggle:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
  /* Closed is the default, and it is the CSS that enforces it — not a hidden
     attribute a script has to remember to set. */
  .fyh__mapSticky{display:none}
  .fyh__two.is-mapOpen .fyh__mapSticky{display:block;margin-top:0.75rem}
  .fyh__map{height:clamp(260px,46vh,420px);max-height:none}
  .fyh__listPane .grid--3{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:640px){
  .fyh__listPane .grid--3{grid-template-columns:1fr}
}
/* Leaflet never loaded — the pane removes itself and the list takes the width
   back rather than leaving a dead column. */
.fyh__two.is-noMap{display:block}

/* ---------------------------------------------------------------------------
   THE PAYMENT BLOCK — figure and disclosure are ONE unit.

   .pay is the visual unit. .pay__figure and .pay__disc are both inside it, they
   are built in the same function call, and break-inside:avoid keeps them on one
   page when printed. The disclosure is 0.8125rem/1.65 at --ink, which is body
   copy — it is deliberately NOT a 10px grey footnote, and it is never inside a
   <details>, a tooltip or a modal. build/audit_payment_search.py asserts all of
   that on the rendered DOM.
   --------------------------------------------------------------------------- */
.pay{margin:0.75rem 0 1.25rem;padding:1rem;background:var(--ivory);
  border:1px solid var(--line);border-radius:var(--radius);break-inside:avoid;
  page-break-inside:avoid}
.pay__head{display:flex;flex-wrap:wrap;align-items:baseline;gap:0.5rem 0.75rem}
.pay__figure{font-family:'Cormorant Garamond',serif;font-size:1.75rem;font-weight:600;
  color:var(--midnight);margin:0;font-variant-numeric:tabular-nums}
.pay__per{font-family:'Jost',sans-serif;font-size:0.75rem;font-weight:400;
  text-transform:uppercase;letter-spacing:.14em;color:var(--muted-aa);margin-left:0.375rem}
.pay__basis{margin:0;font-size:0.8125rem;color:var(--muted-aa)}
.pay__items{margin:0.875rem 0 0;padding:0.875rem 0 0;border-top:1px solid var(--line);
  display:grid;gap:0.25rem}
.pay__item{display:flex;justify-content:space-between;gap:1rem;font-size:0.8125rem;
  color:var(--ink)}
.pay__item dt{margin:0}
.pay__item dd{margin:0;font-variant-numeric:tabular-nums}
.pay__item--total{margin-top:0.375rem;padding-top:0.5rem;border-top:1px solid var(--line);
  font-weight:500;color:var(--midnight)}
.pay__sub{margin:0.75rem 0 0;font-size:0.75rem;line-height:1.65;color:var(--muted-aa)}
.pay__disc{margin:0.75rem 0 0;padding-top:0.75rem;border-top:1px solid var(--line);
  font-size:0.8125rem;line-height:1.65;color:var(--ink)}

@media print{
  .fyh__tabs,.fyh__gate,.fyh__await{display:none}
  .pay,.home{break-inside:avoid;page-break-inside:avoid}
  .pay__disc{color:#000}
}

/* The estimator's standing disclaimer. ABOVE the figure, inside the output
   panel, at readable size — deliberately not the small print at the foot of
   the section, which on a phone sits a screen and a half below the number it
   is supposed to qualify. */
.est__topnote{margin:0 0 1rem;padding-bottom:0.875rem;border-bottom:1px solid var(--line);
  font-size:0.8125rem;line-height:1.6;color:var(--ink)}

/* =============================================================================
   MODEL-HOME CHECK-IN KIOSK (/checkin)
   An iPad on a table, used standing up, by someone who has never seen it before
   and will not be shown how it works. Everything below follows from that:
   60px+ targets, 18px+ type, one action per screen, and no chrome to get lost in.
   Scoped under .kio so it cannot touch the rest of the site.
   ========================================================================== */
.kio-html{height:100%;overflow:hidden;scroll-behavior:auto}
.kio{height:100%;margin:0;overflow:hidden;background:var(--ivory);color:var(--ink);
  font-family:'Jost',sans-serif;
  /* A kiosk has no text selection and no long-press callouts: both only ever
     produce a stuck selection nobody knows how to clear. */
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none;
  -webkit-tap-highlight-color:transparent}
/* Inputs are the ONE exception — a visitor must be able to select and correct
   what they typed. */
.kio input{-webkit-user-select:text;user-select:text}
.kio__stage{position:fixed;inset:0;display:flex;flex-direction:column;
  padding:env(safe-area-inset-top) env(safe-area-inset-right) 0 env(safe-area-inset-left)}
.kio__screen{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
  display:flex;flex-direction:column;padding:clamp(1.5rem,4vw,3rem) clamp(1.25rem,5vw,4rem) 7rem}
.kio__screen[hidden]{display:none}
/* Welcome and thank-you are single statements: centred, nothing to hunt for. */
.kio__screen--welcome,.kio__screen--thanks{align-items:center;justify-content:center;text-align:center}
.kio__screen--form{max-width:820px;width:100%;margin:0 auto}

.kio__langs{display:flex;gap:0.5rem;margin:0 0 clamp(1rem,3vh,2.5rem)}
.kio__langs--form{align-self:flex-end;margin-bottom:1rem}
.kio__lang{min-height:60px;padding:0 1.5rem;font-family:'Jost',sans-serif;font-size:1rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--midnight);background:var(--white);
  border:1px solid var(--line);border-radius:var(--radius);cursor:pointer}
.kio__lang.is-on{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}

.kio__face{width:160px;height:160px;border-radius:50%;object-fit:cover;
  border:1px solid var(--gold);margin:0 0 1.5rem}
.kio__eyebrow{font-family:'Jost',sans-serif;font-size:0.875rem;letter-spacing:.28em;
  text-transform:uppercase;color:var(--gold);margin:0 0 0.75rem}
.kio__title{font-family:'Cormorant Garamond',Georgia,serif;font-weight:600;
  font-size:clamp(2.5rem,7vw,4.5rem);line-height:1.05;color:var(--midnight);margin:0 0 1rem}
.kio__h2{font-family:'Cormorant Garamond',Georgia,serif;font-weight:600;
  font-size:clamp(2rem,5vw,3rem);line-height:1.1;color:var(--midnight);margin:0 0 0.5rem}
.kio__sub{font-size:clamp(1.0625rem,2.2vw,1.375rem);line-height:1.6;color:var(--muted-aa);
  max-width:34ch;margin:0 0 clamp(1.5rem,4vh,2.5rem)}
.kio__screen--form .kio__sub{max-width:48ch}
.kio__sub--tight{margin-bottom:1.75rem}
.kio__host{font-size:0.9375rem;letter-spacing:.06em;color:var(--muted-aa);margin:1.75rem 0 0}
.kio__where{font-size:0.875rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gold);margin:0.5rem 0 0}
.kio__where:empty{display:none}

/* 60px is the floor for EVERY control on this page, not a target to aim near.
   The primary action is 72px because it is pressed with a thumb, standing up,
   by somebody holding a phone in the other hand. */
.kio__btn{min-height:72px;padding:0 clamp(2rem,5vw,3.5rem);font-family:'Jost',sans-serif;
  font-size:1.125rem;letter-spacing:.16em;text-transform:uppercase;font-weight:500;
  border-radius:var(--radius);cursor:pointer;border:1px solid var(--midnight);
  color:var(--ivory);background:var(--midnight);transition:background var(--dur-2) var(--ease)}
.kio__btn--go:active{background:var(--gold);border-color:var(--gold);color:var(--midnight)}
.kio__btn--ghost{background:none;color:var(--midnight)}
.kio__actions{display:flex;flex-wrap:wrap;gap:1rem;margin:2rem 0 0}
.kio__actions .kio__btn{flex:1 1 12rem}
.kio__screen--thanks .kio__btn{margin-top:2rem}

.kio__grid{display:grid;grid-template-columns:1fr 1fr;gap:1.25rem 1.5rem;margin:0 0 1.75rem}
.kio__grid--2{margin-top:1.25rem}
.kio__field{display:flex;flex-direction:column;min-width:0}
.kio__label{font-size:0.9375rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted-aa);margin:0 0 0.5rem}
.kio__opt{font-style:normal;text-transform:none;letter-spacing:.02em;color:var(--placeholder)}
.kio__field input{min-height:64px;padding:0 1rem;font-family:'Jost',sans-serif;
  /* 16px+ or iOS zooms the whole locked viewport on focus. 20px because this is
     read at arm's length on a table, not held up to a face. */
  font-size:20px;color:var(--ink);background:var(--white);
  border:1px solid var(--line);border-radius:var(--radius)}
.kio__field input:focus{outline:2px solid var(--gold);outline-offset:2px;border-color:var(--gold)}
.kio__field input.is-invalid{border-color:var(--redtag);background:rgba(var(--redtag-rgb),.04)}

.kio__block{border:0;padding:0;margin:0 0 1.75rem;min-width:0}
.kio__legend{padding:0;font-size:0.9375rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted-aa);margin:0 0 0.75rem}
.kio__hint{font-size:0.9375rem;color:var(--placeholder);margin:-0.35rem 0 0.75rem}
.kio__chips{display:flex;flex-wrap:wrap;gap:0.75rem}
.kio__chip{min-height:60px;padding:0 1.5rem;font-family:'Jost',sans-serif;font-size:1.0625rem;
  color:var(--midnight);background:var(--white);border:1px solid var(--line);
  border-radius:var(--radius);cursor:pointer;transition:background var(--dur-1) var(--ease)}
.kio__chip.is-on{background:var(--midnight);color:var(--ivory);border-color:var(--midnight)}

/* The consent row is a 60px target in its own right — the box alone is a 20px
   tap on a sheet of glass, and a consent nobody could reliably tick is a
   consent record you cannot rely on either. */
.kio__consent{display:flex;align-items:flex-start;gap:1rem;min-height:60px;
  padding:1.25rem;margin:0 0 0.75rem;background:var(--white);
  border:1px solid var(--line);border-radius:var(--radius);cursor:pointer}
.kio__consent input{width:32px;height:32px;flex:0 0 32px;margin:2px 0 0;accent-color:var(--gold)}
.kio__consentText{font-size:1rem;line-height:1.55;color:var(--ink)}
.kio__privacy{margin:0 0 1.5rem}
.kio__privacy a{display:inline-flex;align-items:center;min-height:60px;font-size:1rem;
  color:var(--gold);text-decoration:none;border-bottom:1px solid rgba(var(--gold-soft-rgb),.55)}

.kio__err{display:block;font-size:0.9375rem;color:var(--redtag);margin:0.4rem 0 0;min-height:0}
.kio__err:empty{display:none}
.kio__err--top{margin:0 0 1rem;font-size:1.0625rem}

.kio__id{position:fixed;left:0;right:0;bottom:0;padding:0.75rem clamp(1.25rem,5vw,4rem)
  calc(0.75rem + env(safe-area-inset-bottom));background:var(--cream);
  border-top:1px solid var(--line)}
.kio__id p{margin:0;font-size:0.75rem;line-height:1.5;color:var(--muted-aa);text-align:center}

/* Portrait iPad and anything narrower: one column, and the fields stack. */
@media (max-width:820px){
  .kio__grid{grid-template-columns:1fr}
  .kio__face{width:120px;height:120px}
  .kio__actions .kio__btn{flex:1 1 100%}
}
/* Landscape iPad is short: the welcome screen loses the portrait head so the
   headline and the Start button both stay above the fold. */
@media (orientation:landscape) and (max-height:820px){
  .kio__face{width:96px;height:96px;margin-bottom:1rem}
  .kio__title{font-size:clamp(2rem,5.5vh,3.25rem)}
  .kio__screen{padding-bottom:6rem}
}

/* ================= ESTIMATE PAYMENT MODAL (assets/estimator-modal.js) =======
   Pricing a home is a lookup, not a destination: this opens over the grid the
   buyer is scanning and closes back to the same pixel. The dialog owns its own
   scroll so the page behind never moves — html.estm-open locks the body.
   At <=640px it is a full-screen sheet rather than a shrunken desktop dialog:
   a centred card at 375px leaves ~16px gutters and puts the output panel below
   the fold, which is the one place the payment must not be. */
html.estm-open { overflow: hidden; }
/* --z-modal, no fallback: the stacking gate requires every layer to come from
   the --z-* scale in :root, and a `var(--z-modal, 9000)` fallback IS a raw
   z-index as far as that gate is concerned — it failed the build on it. */
.estm { position: fixed; inset: 0; z-index: var(--z-modal); display: flex;
  align-items: center; justify-content: center; padding: 2rem 1rem; }
.estm[hidden] { display: none; }
.estm__backdrop { position: absolute; inset: 0; background: rgba(var(--midnight-deep-rgb), .62);
  backdrop-filter: blur(2px); }
.estm__dialog { position: relative; width: min(920px, 100%); max-height: calc(100dvh - 4rem);
  display: flex; flex-direction: column; background: var(--ivory);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 24px 64px rgba(var(--black-rgb), .34); overflow: hidden; }
.estm__head { display: flex; align-items: flex-start; gap: 1rem; padding: 1.25rem 1.5rem;
  background: var(--midnight); color: var(--ivory); }
.estm__eyebrow { margin: 0 0 .35rem; font-family: 'Jost', sans-serif; text-transform: uppercase;
  letter-spacing: .16em; font-size: .625rem; color: var(--gold-soft); }
.estm__title { margin: 0; font-size: 1.375rem; font-weight: 600; line-height: 1.2; }
.estm__meta { margin: .3rem 0 0; font-size: .8125rem; color: rgba(var(--ivory-rgb), .82);
  font-family: 'Jost', sans-serif; letter-spacing: .04em; }
.estm__x { margin-left: auto; flex: none; background: none; border: 0; color: var(--ivory);
  font-size: 1.75rem; line-height: 1; cursor: pointer; padding: 0 .25rem; opacity: .85; }
.estm__x:hover { opacity: 1; color: var(--gold-soft); }
.estm__body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.5rem; padding: 1.5rem; overflow-y: auto; }
.estm__field { margin-bottom: 1.15rem; }
.estm__lbl { display: block; font-family: 'Jost', sans-serif; text-transform: uppercase;
  letter-spacing: .14em; font-size: .625rem; color: var(--muted-aa); margin-bottom: .5rem; }
.estm__pills { display: flex; flex-wrap: wrap; gap: .4rem; }
.estm__pill { display: flex; flex-direction: column; align-items: center; gap: 2px;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .5rem .7rem; cursor: pointer; font-family: 'Jost', sans-serif; font-size: .8125rem;
  color: var(--midnight); min-height: 44px; justify-content: center; }
.estm__pill .estm__amt { font-size: .625rem; color: var(--muted-aa); letter-spacing: .02em; }
.estm__pill.is-on { background: var(--midnight); border-color: var(--midnight); color: var(--ivory); }
.estm__pill.is-on .estm__amt { color: var(--gold-soft); }
.estm__range { width: 100%; }
.estm__fixed { border-top: 1px solid var(--line); padding-top: 1rem; }
.estm__fixrows { margin: 0; }
.estm__fixrows > div { display: flex; justify-content: space-between; align-items: baseline;
  padding: .3rem 0; border-bottom: 1px solid rgba(var(--gold-rgb), .12); }
.estm__fixrows dt { font-size: .8125rem; color: var(--muted-aa); }
.estm__fixrows dd { margin: 0; font-size: .8125rem; font-weight: 600; color: var(--midnight);
  font-variant-numeric: tabular-nums; }
.estm__fixnote { margin: .6rem 0 0; font-size: .6875rem; line-height: 1.5; color: var(--muted-aa); }
.estm__out { background: var(--midnight); color: var(--ivory); border-radius: var(--radius);
  padding: 1.25rem; display: flex; flex-direction: column; }
.estm__topnote { margin: 0 0 .75rem; font-size: .6875rem; line-height: 1.5;
  color: rgba(var(--ivory-rgb), .78); }
.estm__olbl { margin: .5rem 0 .1rem; font-family: 'Jost', sans-serif; text-transform: uppercase;
  letter-spacing: .14em; font-size: .625rem; color: var(--gold-soft); }
.estm__big { margin: 0; font-family: 'Cormorant Garamond', serif; font-size: 2.25rem;
  font-weight: 600; line-height: 1.1; }
.estm__big--sub { font-size: 1.75rem; }
.estm__detail, .estm__basis { margin: .5rem 0 0; font-size: .75rem; line-height: 1.55;
  color: rgba(var(--ivory-rgb), .82); }
.estm__regz { margin-top: 1rem; background: rgba(var(--midnight-rgb), .45);
  border-color: rgba(var(--ivory-rgb), .24); }
.estm__regz .regz__terms { color: rgba(var(--ivory-rgb), .92); }
.estm__regz .regz__standing { color: rgba(var(--ivory-rgb), .78); }
.estm__cta { display: inline-block; margin-top: 1rem; text-align: center;
  font-family: 'Jost', sans-serif; text-transform: uppercase; letter-spacing: .16em;
  font-size: .75rem; font-weight: 600; color: var(--midnight); background: var(--gold);
  border-radius: var(--radius); padding: .8rem 1rem; }
.estm__cta:hover { background: var(--gold-soft); }
@media (max-width: 860px) {
  .estm__body { grid-template-columns: 1fr; }
}
/* FULL-SCREEN SHEET on phones — not a shrunken dialog. */
@media (max-width: 640px) {
  .estm { padding: 0; align-items: stretch; }
  .estm__dialog { width: 100%; max-width: none; max-height: none; height: 100dvh;
    border: 0; border-radius: 0; }
  .estm__body { padding: 1rem; gap: 1rem; }
  /* --z-local-raise (=1), not a bare 1: the stacking gate rejects any layer
     that is not drawn from the --z-* scale, whatever its numeric value. */
  .estm__head { padding: 1rem; position: sticky; top: 0; z-index: var(--z-local-raise); }
  .estm__big { font-size: 2rem; }
}

/* ============== AGENT ATTRIBUTION BADGE (assets/agent-attrib.js) ============
   Persistent but subtle: this states a relationship, it is not a call to
   action. Sits above the content and clear of the Call/Text bar and the chat
   launcher, both of which own the bottom-right on mobile. Dismissing it hides
   the badge only — the attribution itself is untouched. */
.agentbadge{position:fixed;left:12px;bottom:12px;z-index:var(--z-dropdown);
  display:inline-flex;align-items:center;gap:.5rem;max-width:min(92vw,26rem);
  padding:.5rem .6rem .5rem .85rem;border-radius:40px;
  background:rgba(var(--midnight-rgb),.92);color:var(--ivory);
  border:1px solid rgba(var(--gold-rgb),.45);
  box-shadow:0 6px 20px rgba(var(--black-rgb),.28);
  font-family:'Jost',sans-serif;font-size:.75rem;letter-spacing:.03em}
.agentbadge__txt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.agentbadge__x{flex:none;background:none;border:0;color:rgba(var(--ivory-rgb),.7);
  font-size:1.1rem;line-height:1;cursor:pointer;padding:0 .15rem;min-width:28px;min-height:28px}
.agentbadge__x:hover{color:var(--gold-soft)}
@media (max-width:640px){
  /* Clear of the Call/Text bar, which owns the bottom edge on phones. */
  .agentbadge{bottom:calc(var(--callbar-h) + env(safe-area-inset-bottom) + 12px);
    left:10px;right:10px;max-width:none}
}

/* THE COLLAPSED FORM. The × no longer removes the ribbon — it shrinks it to
   this pill, which reopens on click. A badged page has had every other name
   taken off it, so "dismissed to nothing" would leave the site branded to
   nobody; see the comment in assets/agent-attrib.js. The pill is deliberately
   the size of a touch target and nothing more. */
.agentbadge.is-collapsed{gap:0;padding:0;max-width:none;border-radius:50%}
.agentbadge__pill{width:38px;height:38px;flex:none;border-radius:50%;
  display:grid;place-items:center;cursor:pointer;
  background:none;border:0;color:var(--gold-soft);
  font-family:'Jost',sans-serif;font-size:.75rem;letter-spacing:.04em}
.agentbadge__pill:hover{color:var(--ivory)}
@media (max-width:640px){
  /* Collapsed, it stops spanning the viewport — the whole point is to get out
     of the way, and a full-width bar does not. */
  .agentbadge.is-collapsed{right:auto;width:38px}
}

/* PRE-PAINT PROMO SUPPRESSION.

   stripPromo() in assets/agent-attrib.js REMOVES these surfaces from the DOM,
   and removal — not hiding — remains the guarantee; build/audit_agent_promo.py
   asserts on innerHTML precisely so that a display:none phone number cannot
   pass for a deleted one. Nothing here changes that.

   What this covers is the window BEFORE the removal can happen. stripPromo has
   to wait for DOMContentLoaded because it edits the footer, and the footer is
   the last thing to parse. Measured at 375px over a 400ms / 400kbps link, the
   page paints at 19.0s and the deferred script runs at 24.1s — five seconds in
   which a badged visitor is looking at Tony's sticky "Call or Text" bar, his
   header phone button and his footer column, on the session that exists
   specifically to not show them any of it.

   assets/agent-ribbon-boot.js sets .tg-promo-off synchronously at the top of
   <body>, before the first frame, so these never paint at all. The class is
   only ever set for a REGISTERED agent tag, so an ordinary visit is untouched.
   These five selectors are the ones stripPromo names by class; the inline
   promo links it also removes are left to it, being far less conspicuous than
   a fixed bar across the bottom of the screen. */
html.tg-promo-off .footer__brand,
html.tg-promo-off .footer__social,
html.tg-promo-off #contact,
html.tg-promo-off .mobile-callbar,
html.tg-promo-off .nav__tel{display:none !important}

/* THE FOOTER'S AGENT BLOCK — what replaces Tony's promo column on a badged
   session. Same visual weight as the column it stands in for, so the footer
   grid keeps its three-across rhythm instead of collapsing to two. */
.footer__agent-hd{font-family:'Jost',sans-serif;font-size:.6875rem;
  letter-spacing:.16em;text-transform:uppercase;color:rgba(var(--ivory-rgb),.62);
  margin:0 0 .35rem}
.footer__agent-who{font-family:'Cormorant Garamond',serif;font-size:1.375rem;
  line-height:1.25;margin:0}
.footer__agent-brk{font-family:'Jost',sans-serif;font-size:.8125rem;
  color:rgba(var(--ivory-rgb),.72);letter-spacing:.02em}

/* THE GENERIC CHAT MARK — the badged stand-in for the headshot, in the
   launcher, the teaser, the panel header and every assistant bubble. It wears
   the class the <img> would have worn, so it inherits that slot's size and
   ring; these rules only supply what an <img> got for free. */
.tgchat-mark{display:grid;place-items:center;overflow:hidden;
  background:var(--midnight-2);color:var(--gold-soft)}
.tgchat-mark svg{width:62%;height:62%}
.tgchat-launch__av .tgchat-mark{position:absolute;inset:0}
.tgchat-head__avwrap .tgchat-mark{position:absolute;inset:0;border:none;box-shadow:none}
.tgchat-av--mark{padding:0}

/* THE EXPIRED-RATE NOTICE. Hidden until assets/estimator.js puts
   .is-rate-expired on #estimator, which it does only when EST_PROMO_ACTIVE is
   false — i.e. the published programme's close-by date has passed in
   America/New_York, evaluated in the browser, so it turns itself on with no
   redeploy. Once the visitor types a rate of their own the estimator adds
   .is-rate-supplied and the notice steps aside: it exists to explain an empty
   field, not to nag someone who has already filled it. */
#estimator .est__expired{display:none}
#estimator.is-rate-expired .est__expired{display:block;margin:.6rem 0 0;
  font-size:.86rem;line-height:1.5;color:var(--ink);opacity:.9;max-width:46ch}
#estimator.is-rate-expired.is-rate-supplied .est__expired{opacity:.62}
/* =============================================================================
   PUBLISHED CORPORATE SCENARIO — the D.R. Horton / DHI Mortgage rate band.

   ONE CLASS FOR BOTH FIGURES, AND THAT IS THE POINT. .promo__num carries the
   rate and the APR identically: same size, same weight, same colour. The flyer
   sets 4.99% at roughly three times the size of 5.843% APR, and the 2026-08-04
   ruling says the rate may never be more conspicuous than the APR — so the
   pair renders at equal weight in the flyer's ORDER. Giving either figure its
   own modifier class is how that rule gets lost, so there is no second class to
   reach for. build/audit_equal_weight.py measures the rendered type and fails
   the build if they diverge.

   The terms live in a <details> for LENGTH, not for prominence: the flyer's
   disclosure paragraph and its footer disclaimer run to ~1,900 characters, and
   a band that pushes the page down by a screen and a half gets removed by
   whoever next redesigns the homepage — at which point the figures stay and the
   terms go. Collapsed, they are in the DOM, in the accessibility tree, and one
   keystroke away. Not collapsed, they are one redesign from being deleted.
   ========================================================================== */
.promo-band{max-width:none;background:var(--cream);padding-left:0;padding-right:0}
.promo__inner{max-width:var(--max);margin:0 auto;padding:0 2rem;text-align:center}
.promo__eyebrow{color:var(--gold)}
.promo__title{font-size:clamp(1.5rem,3vw,2.1rem);font-weight:500;color:var(--midnight);
  margin:.55rem 0 1.4rem;line-height:1.18}

.promo__figures{display:flex;justify-content:center;align-items:flex-start;
  gap:clamp(1.75rem,6vw,4rem);margin:0 0 1.25rem;flex-wrap:wrap;
  /* SAME WEIGHT AS THE FIGURES, on purpose. audit_equal_weight.py's E3 fails
     any figure heavier than the line it sits in; matching the container here is
     what lets the pair be large without either one being "bolder than its own
     line". Change one of these two numbers and the gate goes red. */
  font-weight:500}
.promo__fig{display:flex;flex-direction:column;align-items:center;gap:.3rem}
/* EQUAL WEIGHT. Do not add a --lead / --hero modifier to either figure. */
.promo__num{font-size:clamp(2.1rem,5.4vw,3.1rem);font-weight:500;line-height:1;
  color:var(--midnight);letter-spacing:-.01em;font-variant-numeric:tabular-nums}
/* Inside .promo__num, not beside it — the compliance probe reads the figure
   span's text to tell a rate from an APR. display:block keeps the visual
   stacking the design wants without splitting the string it has to match. */
.promo__lab{display:block;font-size:.76rem;font-weight:400;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink);opacity:.72;margin-top:.35rem}

.promo__scenario{max-width:640px;margin:0 auto;color:var(--ink);
  font-size:.98rem;line-height:1.6}

.promo__terms{max-width:760px;margin:1.6rem auto 0;text-align:left}
.promo__terms>summary{cursor:pointer;font-size:.86rem;letter-spacing:.03em;
  color:var(--ink);opacity:.85;text-align:center;list-style:none}
.promo__terms>summary::-webkit-details-marker{display:none}
.promo__terms>summary::after{content:" \25be";opacity:.6}
.promo__terms[open]>summary::after{content:" \25b4"}
.promo__legal{margin-top:1rem}
.promo__avail{font-size:.9rem;line-height:1.55;color:var(--ink);margin:0 0 .6rem}
.promo__disc{font-size:.84rem;line-height:1.55;color:var(--ink);opacity:.9;margin:0 0 .8rem}
.promo__fine{font-size:.74rem;line-height:1.5;color:var(--ink);opacity:.78;margin:0 0 .6rem}
.promo__eho{font-weight:500;opacity:.85}

@media(max-width:539px){
  /* The two figures stay SIDE BY SIDE at 375px. Stacking them would put the
     rate above the APR at full width each, which reads as a headline with a
     footnote — the exact hierarchy the ruling forbids. */
  .promo__figures{gap:1.5rem;flex-wrap:nowrap}
  .promo__num{font-size:1.85rem}
  .promo__inner{padding:0 1.25rem}
}

/* --- SHARE A FLOOR PLAN (brief section 3) -------------------------------- */
/* The control sits inside the card it shares, so the card's own data-* are the
   facts it composes from — no lookup, no chance of shipping another plan's
   numbers. */
.share-btn{position:absolute;top:.5rem;right:.5rem;z-index:2;display:inline-flex;
  align-items:center;gap:.3rem;padding:.3rem .6rem;border:1px solid var(--line,#d8d4cc);
  border-radius:999px;background:var(--paper,#fff);color:var(--ink,#2b2f35);
  font-family:'Jost',sans-serif;font-size:.72rem;line-height:1;cursor:pointer}
.share-btn:hover{border-color:var(--ink,#2b2f35)}
.share-btn:focus-visible{outline:2px solid var(--ink,#2b2f35);outline-offset:2px}
/* THE DESKTOP CONFIRMATION IS THE FEATURE, not decoration: a copy that gives no
   feedback is indistinguishable from a dead button, and the user's next move is
   to click it again. */
.share-btn[data-shared] .share-note{position:absolute;top:calc(100% + .35rem);right:0;
  white-space:nowrap;background:var(--ink,#2b2f35);color:var(--paper,#fff);
  padding:.25rem .5rem;border-radius:6px;font-size:.68rem}
.home,.plan-card{position:relative}
@media (prefers-reduced-motion:no-preference){
  .share-btn[data-shared]{transition:border-color .15s ease}
}
