
/*! Squarespace LESS Compiler  (less.js language v1.3.3)  */
.header-title-logo img{content:url("https://static1.squarespace.com/static/681e1bcc9c148c17e1ec59b0/t/683742272326994d0150450e/1748451879598/Elevated+-+Logo+-+Black+-+Transparent.png")}.homepage .header-title-logo img{content:url("https://static1.squarespace.com/static/681e1bcc9c148c17e1ec59b0/t/68374227536606708fead0a5/1748451879605/Elevated+-+Logo+-+White+-+Transparent.png")}.sqs-block-markdown a,.sqs-block-markdown a:link,.sqs-block-markdown a:visited{color:#1a1a1a;font-weight:700;text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:3px}.sqs-block-markdown a:hover{color:#555;text-decoration-thickness:2px}:root{--eabc-ink:#2e2e2f;--eabc-paper:#fafafa;--eabc-sand:#dbd7ce;--eabc-muted:rgba(0,0,0,.58)}.eabc-card{padding:2.75rem 2rem;background:var(--eabc-sand);border-radius:6.4px;text-align:center}.eabc-eyebrow{margin:0 0 .6rem;font-family:var(--primary-button-font-font-family,"Hanken Grotesk"),system-ui,sans-serif;font-size:.75rem;font-weight:400;text-transform:uppercase;letter-spacing:.16em;color:var(--eabc-muted)}.eabc-heading{font-family:var(--heading-font-font-family,"Cormorant Garamond"),Georgia,serif;font-weight:500;font-size:2.1rem;line-height:1.12;letter-spacing:-.005em;margin:0 0 .9rem;color:var(--eabc-ink)}.eabc-body{margin:0 auto 1.6rem;max-width:520px;color:var(--eabc-ink);font-size:1.05rem;line-height:1.6}.eabc-btn{display:inline-block;font-family:var(--primary-button-font-font-family,"Hanken Grotesk"),system-ui,sans-serif;font-weight:400;font-size:1rem;text-transform:uppercase;letter-spacing:.04em;padding:1.05rem 2.2rem;background:var(--eabc-ink);color:var(--eabc-paper);border:1px solid var(--eabc-ink);border-radius:6.4px;text-decoration:none;line-height:1;transition:background .2s ease}.eabc-btn:hover{background:#000;color:var(--eabc-paper);text-decoration:none}.eabc-fineprint{margin:1.25rem 0 0;font-family:var(--primary-button-font-font-family,"Hanken Grotesk"),system-ui,sans-serif;font-size:.8rem;letter-spacing:.02em;color:var(--eabc-muted)}@media (max-width:520px){.eabc-card{padding:2rem 1.25rem}.eabc-heading{font-size:1.7rem}}section[data-section-id="6a3ab13b2596061e437cf42f"] .fe-block{grid-column:-1 !important}section[data-section-id="6a3ab13b2596061e437cf42f"] p,section[data-section-id="6a3ab13b2596061e437cf42f"] h1{text-align:center !important}
/* elevated_native_contact_form() (inc/native-contact-form.php), the form that
   replaces a Tally embed one surface at a time: `.ea-ncf` + `.eabc-form` on
   the <form>, so it inherits max-width/margin resets a surface already scopes
   to `.eabc-form` (see e.g. .ea-hcontact .eabc-form) without duplicating them
   here. Two fields per row on desktop, matching the two-up layout Tally used
   to lay First/Last and Email/Phone in; wraps to one column under 520px the
   same way the embed's own fields did. Shared sitewide rather than living next
   to any one surface, because every surface it rolls out to uses it as-is. */
.ea-ncf{display:flex;flex-direction:column;gap:1.1rem}
/* [hidden] and .ea-ncf are equal specificity, and this rule's own display:flex
   would otherwise win on source order once the JS hides the form after
   submit - toggling the hidden ATTRIBUTE (not inline style, for a11y) still
   needs this to actually disappear. */
.ea-ncf[hidden]{display:none}
.ea-ncf__row{display:grid;grid-template-columns:1fr 1fr;gap:1.1rem}
.ea-ncf__field{display:flex;flex-direction:column;gap:.4rem;min-width:0}
.ea-ncf__field--full{grid-column:1/-1}
.ea-ncf__label{font-family:var(--primary-button-font-font-family,"Hanken Grotesk"),system-ui,sans-serif;
  font-size:.72rem;font-weight:400;text-transform:uppercase;letter-spacing:.16em;
  color:var(--eabc-muted,rgba(0,0,0,.58))}
.ea-ncf input,
.ea-ncf textarea{font-family:"EB Garamond",var(--body-font-font-family),Georgia,serif;
  font-size:1rem;padding:.75rem .9rem;border:1px solid rgba(0,0,0,.25);
  border-radius:6.4px;background:#fff;color:var(--eabc-ink,#2e2e2f);width:100%;
  box-sizing:border-box}
.ea-ncf textarea{resize:vertical;min-height:5.5rem}
.ea-ncf input:focus-visible,
.ea-ncf textarea:focus-visible{outline:2px solid var(--eabc-ink,#2e2e2f);outline-offset:1px}
.ea-ncf__submit{align-self:flex-start;border:none;cursor:pointer;font:inherit;
  display:inline-flex;align-items:center;gap:.65rem}
.ea-ncf__submit:disabled{opacity:.75;cursor:default}

/* The spinner only exists while .ea-ncf-wrap--sending is set (submit, until
   the success swap below), so a page that never JS-enhances just shows a
   plain "Send" button with nothing extra taking up space next to it. */
.ea-ncf__spinner{display:none;width:14px;height:14px;flex:0 0 auto;
  border-radius:50%;border:2px solid rgba(250,250,250,.35);
  border-top-color:var(--eabc-paper,#fafafa);animation:ea-ncf-spin .7s linear infinite}
.ea-ncf-wrap--sending .ea-ncf__spinner{display:inline-block}
.ea-ncf-wrap--sending .ea-ncf__submit-label{opacity:.75}
@keyframes ea-ncf-spin{to{transform:rotate(360deg)}}

/* The success panel a submission swaps in for the whole form, not a fine
   print line under it: a checkmark, a heading at the same weight as
   .eabc-heading's smaller siblings, and the confirmation copy below it,
   fading and lifting in over the half second the spinner already bought. */
.ea-ncf__success{text-align:center;padding:.5rem 0;opacity:0;transform:translateY(6px);
  transition:opacity .35s ease,transform .35s ease}
.ea-ncf__success.is-visible{opacity:1;transform:translateY(0)}
.ea-ncf__success-icon{display:block;width:44px;height:44px;margin:0 auto .9rem;
  color:var(--eabc-ink,#2e2e2f)}
.ea-ncf__success-title{margin:0 0 .5rem;
  font-family:var(--heading-font-font-family,"Cormorant Garamond"),Georgia,serif;
  font-weight:500;font-size:1.5rem;line-height:1.2;color:var(--eabc-ink,#2e2e2f)}
.ea-ncf__success-body{margin:0 auto;max-width:380px;
  font-family:"EB Garamond",var(--body-font-font-family),Georgia,serif;
  font-size:1.05rem;line-height:1.5;color:var(--eabc-muted,rgba(0,0,0,.58))}

@media (max-width:520px){
  .ea-ncf__row{grid-template-columns:1fr}
}
@media (prefers-reduced-motion:reduce){
  .ea-ncf__spinner{animation:none}
  .ea-ncf__success{transition:none}
}

/* ---------------------------------------------------------------------------
   THE HAIRLINE RULE, and the one way every ruled list on this site uses it.

   `1px solid rgba(0,0,0,.16)` is the site's hairline. Several components use it
   in place of a photograph, to give a text-only row or card something to sit
   against: .ea-hood__item, .ea-kc__card, .ea-hcontact__item, .ea-contact__item,
   .ea-open__stat, .ea-mw__stat at phone widths.

   IT IS A DIVIDER, NOT A BOX. Zeve, on three of them at once: "why are there
   lines above the first items and below the last". A rule above the first item
   and a rule below the last one are not separating anything from anything; they
   are drawing a frame around the list. Only the rules BETWEEN two items are
   doing work.

   THE ONE EXPRESSION, and it is one rule with one parameter rather than a
   different trick per component, because these lists are not built the same
   way (some are single-column <ul>s, some are row-filled multi-column grids
   that reflow at two breakpoints):

     1. draw the hairline as `border-top` on EVERY item;
     2. remove it from the items in the FIRST ROW, which is `:nth-child(-n+N)`
        where N is the column count at that breakpoint, degenerating to
        `:first-child` for a single-column list;
     3. never draw a `border-bottom` anywhere.

   WHY border-top AND NOT border-bottom-on-all-but-the-last. For a grid, the
   first row is always exactly `:nth-child(-n+N)` whatever the item count is,
   but the last row is only `:nth-last-child(-n+N)` when the last row happens to
   be full. Suppressing the top is therefore correct for any number of items;
   suppressing the bottom is correct only by luck. N changes with the track
   count, so step 2 is restated inside each breakpoint that changes the columns:
   restore the rule first, then suppress the new first row. Both selectors carry
   the same specificity, so source order decides and the restore must come
   first.

   PADDING IS NEVER TOUCHED, only the border. The suppressed items keep the top
   padding that was measured for them, so nothing reflows and a grid's rows stay
   aligned with each other.
   --------------------------------------------------------------------------- */

/* Auto-CTA block, ported from the Squarespace footer Code Injection. */
.ea-autocta{margin:3rem auto 1rem;max-width:760px;font-family:var(--body-font-font-family,"EB Garamond"),Georgia,serif;line-height:1.55}
.ea-autocta .eabc-form{max-width:520px;margin:0 auto;text-align:left}

/* Scroll reveal. Squarespace animated [data-animation-role] elements from its
   site bundle; the markup ships with no initial-state CSS of its own, so the
   states live here alongside the rebuilt runtime. */
.ea-reveal{opacity:0;transform:translateY(18px);will-change:opacity,transform}
/* Applied to content that was already on screen at load: visible instantly,
   with no transition, so nothing pops in after the page has painted. */
.ea-reveal--shown{opacity:1;transform:none}
.ea-reveal--done{opacity:1;transform:none;transition:opacity .75s cubic-bezier(.22,.61,.36,1),transform .75s cubic-bezier(.22,.61,.36,1)}
@media (prefers-reduced-motion:reduce){.ea-reveal,.ea-reveal--done{opacity:1;transform:none;transition:none}}

/* Carousel arrows are rendered by the markup but were inert without the bundle. */
.user-items-list-carousel__slides::-webkit-scrollbar{display:none}
.user-items-list-carousel [class*="arrow-button"]{cursor:pointer;background:none;border:0}
.user-items-list-carousel [class*="arrow-button"][disabled]{opacity:.35;cursor:default}

/* Section background video. Squarespace built this element in its site bundle;
   rebuilt here against the same .section-background container. */
/* Do NOT restate .section-background positioning here. The bundle positions it
   (absolute, with a computed top offset); overriding it from this file -- which
   loads later -- collapsed the container the video anchors to, so the video had
   zero height and was invisible even though it was present and serving 200. */
.ea-bg-video{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;z-index:0;pointer-events:none}
.section-background>img{position:relative;z-index:1}

/* THE HERO SCRIM. Zeve: "the current live elevated website has more of a dark
   background over the video which makes it easier to read the navigation menu."

   WHAT LIVE ACTUALLY DOES, measured, not guessed. Live carries
   `filter:brightness(0.55)` on div.sqs-video-background-native.content-fill,
   which is the full 1440x868 hero, a flat multiplier over the whole clip and
   not a gradient. Chrome applies the shorthand filter functions in sRGB, so
   brightness(k) is pixel identical to compositing black at alpha 1-k over the
   same content: rgb(200,120,60) reads back (110,66,33) under both. Live is
   therefore a FLAT BLACK SCRIM AT ALPHA .45 across the entire hero.

   WHAT WE HAD: nothing. No filter, no overlay, no scrim of any kind. That is
   the whole of Zeve's complaint.

   WHY NOT SIMPLY COPY .45. Sampling the clip at every one of its 102
   quarter-second frames, mapping each on-screen rectangle back through
   object-fit:cover into video pixels, live's .45 leaves the nav BELOW the
   WCAG AA floor on the worst pixel of the worst frame: paper #fafafa on the
   band behind "Neighborhoods" is 4.05:1 where 1.4.3 wants 4.5:1. It clears the
   bar on the rectangle MEAN (4.78:1) and fails on the pixels that actually sit
   under the glyphs. Live is a Squarespace default nobody measured, and this is
   where it shows.

   WHY A GRADIENT AND NOT A HEAVIER FLAT. The top of this clip is the bright
   part of it. Frame-mean relative luminance across the header band runs .4773
   to .4952, against .2052 to .2274 for the hero as a whole: the nav sits on
   video more than twice as bright as the rest of the section. Darkening the
   whole hero to fix a band that is 2.3x brighter than the rest spends contrast
   and mood everywhere to buy legibility in the top 130px.

   WHY THE BASE IS STILL LIVE'S .45 AND NOT LESS. A top-only gradient was
   measured and is not sufficient on its own. The h1 sits at y=392, well below
   any header scrim, and sand #dbd7ce on the raw clip is 1.03:1 on its worst
   pixel and 2.20:1 on its top 1%: it fails 1.4.3's 3:1 large-text floor today
   and a gradient that has decayed to zero by then leaves it failing. .45 is
   the lightest flat base that holds the h1 at 3:1 on EVERY pixel of every
   frame (3.19:1 at 1440, 4.05:1 at 390). So live's number is doing real work
   below the fold and is kept exactly.

   THE SHAPE: .58 held flat across the header band, then tapered to live's .45
   by 340px and flat at .45 to the bottom of the hero. 130px covers the header
   at both breakpoints (127.73px at 1440, 90.78px at 390) so every nav element
   gets the same treatment rather than a ramp across its own height. Nothing
   below 340px is darker than live already is.

   WHAT IT BUYS, worst of 102 frames, worst single pixel, both breakpoints:

     nav links, paper #fafafa      1.26:1  ->  6.20:1   (1.4.3 wants 4.5:1)
     wordmark, white               1.37:1  ->  6.64:1   (1.4.11 wants 3:1)
     mail and Instagram icons      2.73:1  ->  9.90:1   (1.4.11 wants 3:1)
     burger bars at 390            1.61:1  ->  7.28:1   (1.4.11 wants 3:1)
     h1, sand #dbd7ce              1.03:1  ->  3.19:1   (1.4.3 wants 3:1)

   Every nav link also clears 7:1, the AAA threshold, on the worst-frame mean.

   THE HERO BUTTON IS UNCHANGED WHERE IT MATTERS AND BETTER WHERE IT MOVES. Its
   label never touches the video: ink #2e2e2f on an opaque paper plate is
   13.00:1 on every frame, before and after. Its plate edge sat at 3.61:1
   because the paper and ink curves cross at L=.229 and the ring reached that
   crossing; under a .45 base no ring pixel gets near it any more, so the
   measured worst edge is 5.00:1 at 1440 and 4.83:1 at 390. The theoretical
   3.61:1 floor for a paper-in-ink edge is unchanged, because a black scrim can
   only move ring luminance down, never up.

   THE SELECTOR FOLLOWS THE VIDEO, not the page. `:has(> .ea-bg-video)` is true
   only where a hero background video exists, which today is the front page and
   nowhere else. It is deliberately not keyed to .homepage or to a page slug:
   the front page has already changed identity once during this work, and the
   archive heroes in .ea-archive-hero and the building heroes reuse
   .section-background with a still image and must not be darkened.

   z-index 1 sits it above the video, which is z-index 0, and level with the
   still-image case just below. .section-background is positioned by the
   bundle, so this is a child of an existing containing block and does not
   restate any of its positioning, per the warning above. */
.section-background:has(> .ea-bg-video)::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(to bottom,
    rgba(0,0,0,.58) 0,
    rgba(0,0,0,.58) 130px,
    rgba(0,0,0,.45) 340px,
    rgba(0,0,0,.45) 100%);
}

/* Summary-block pager. Squarespace renders these buttons but wires them in its
   site bundle; without arrows the Knowledge Center section cannot be advanced. */
/* Pager arrows.
   Live renders these as SVG glyphs injected by Squarespace's component JS.
   Redrawn here as thin CSS chevrons. The explicit border/background resets
   matter: the bundle styles these controls as buttons, which showed up as two
   outlined squares instead of arrows. */
.summary-carousel-pager{display:flex;gap:.9rem;align-items:center}
.summary-carousel-pager span,
.summary-carousel-pager button{
  cursor:pointer;background:none!important;border:0!important;box-shadow:none!important;
  width:1.1rem;height:1.1rem;position:relative;display:inline-block;padding:0;
  border-radius:0;font-size:0;line-height:0;
  /* Explicit colour, NOT inherit. The section theme sets colour to white here,
     so currentColor drew white chevrons on a white background: rendered,
     positioned, opacity 1 and completely invisible. */
  color:var(--eabc-ink,#2e2e2f);
}
.summary-carousel-pager span::after,
.summary-carousel-pager button::after{
  content:"";position:absolute;top:50%;left:50%;width:.55rem;height:.55rem;
  border-top:1px solid currentColor;border-right:1px solid currentColor;
}
/* The bundle colours .summary-carousel-pager-prev/.next directly, which beats
   the shared span rule above, so state the colour on those classes too. */
.summary-carousel-pager .summary-carousel-pager-prev,
.summary-carousel-pager .summary-carousel-pager-next{color:var(--eabc-ink,#2e2e2f)!important}
.summary-carousel-pager-prev::after{transform:translate(-30%,-50%) rotate(-135deg)}
.summary-carousel-pager-next::after{transform:translate(-70%,-50%) rotate(45deg)}
.summary-carousel-pager span::before,
.summary-carousel-pager button::before{content:none!important}
.summary-carousel-pager .ea-pager--off{opacity:.25;cursor:default}
.summary-block-setting-design-carousel .summary-item-list.sqs-gallery::-webkit-scrollbar{display:none}

/* Knowledge Center summary block.
   The pager sits top-right under the heading on the live site, and the ported
   bundle only styles it once Squarespace's JS has laid the block out. */
/* The bundle sets .summary-block-header{overflow:hidden}. An absolutely
   positioned pager hanging below that box was clipped to nothing -- the arrows
   measured 32x32 but their container measured 0 tall. Keep the pager in flow. */
.summary-block-header{display:flex;align-items:flex-start;justify-content:center;position:relative;gap:1rem;flex-wrap:wrap;overflow:visible!important;min-height:2.5rem}
.summary-block-header .summary-heading{flex:1 1 100%;text-align:center}
.summary-block-header .summary-carousel-pager{position:absolute;right:0;top:100%;display:flex;gap:.75rem;z-index:2}
.summary-item{min-width:0}
.summary-item .summary-title{margin:0 0 .55rem}
.summary-item .summary-excerpt p{margin:0 0 .9rem}
.summary-item .summary-metadata-item--date{font-size:.82rem;opacity:.62}
.summary-item .summary-metadata-container--below-content{margin-top:auto}
.summary-content{display:flex;flex-direction:column;height:100%}

/* Summary carousel track. Items keep their inline 25.25% widths (four across,
   as live); this only makes the row scroll horizontally in place of the
   carousel controller Squarespace would have run. */
/* Carousel-design blocks ONLY. Summary blocks come in several designs; the
   autogrid variant (used for "Top Buildings" on neighborhood guides) is a
   float layout, and applying this flex rule to it stretched each card to the
   full content width, showing one building instead of five. */
.summary-block-setting-design-carousel .summary-item-list.sqs-gallery{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;align-items:flex-start}
.summary-block-setting-design-carousel .summary-item-list.sqs-gallery>.summary-item{flex:0 0 auto}

/* Summary block type scale.
   The component stylesheet's winning rule is
   .sqs-block[data-definition-name=...] .summary-block-wrapper .summary-title
   { font-size: var(--summary-title-font-size) }, and Squarespace's summary
   component JS is what defines those custom properties at runtime. Undefined,
   var() falls back to the inherited 21.18px -- which is why the titles and
   excerpts were oversized despite every class and attribute matching live.
   Values below are the live site's own computed values. */
.sqs-block-summary-v2,
.sqs-block[data-definition-name="website.components.summary"]{
  --summary-title-font-size:20px;
  --summary-excerpt-font-size:14px;
}

/* Neighborhood "Top Buildings" cards.
   Scoped to the autogrid design so the Knowledge Center carousel on the
   homepage keeps its dates, which the live site shows there. */
.summary-block-setting-design-autogrid .summary-item .summary-title{padding-top:10px}
/* !important is needed here: the component stylesheet sets display on
   .summary-metadata-item with higher specificity via its
   [data-definition-name] scope. */
.summary-block-setting-design-autogrid .summary-item .summary-metadata-container,
.summary-block-setting-design-autogrid .summary-item .summary-metadata,
.summary-block-setting-design-autogrid .summary-item .summary-metadata-item,
.summary-block-setting-design-autogrid .summary-item .summary-metadata-item--date,
.summary-block-setting-design-autogrid .summary-item time{display:none!important}

/* ---------------------------------------------------------------------------
   Mobile navigation.

   The burger markup ported across intact, but the stylesheet that draws its
   three bars is served by a Squarespace component bundle that was not part of
   the CSS capture -- so the button existed at 0x0 with an invisible icon and
   nothing to tap. The open state also depends on
   `.header--menu-open .header-menu.display-hamburger-on-desktop`, and our menu
   does not carry that second class, so the rule could never match.

   Both are supplied here, keyed to the same classes Squarespace uses.
   --------------------------------------------------------------------------- */
/* Do NOT set display on .header-burger.
   The bundle keeps it display:none and reveals it only inside
   .header-display-mobile. Forcing display:flex here made the hidden DESKTOP
   burger visible too, so the hamburger appeared next to the full nav. */
.header-burger-btn{
  width:44px;height:44px;padding:0;margin:0;cursor:pointer;
  background:none;border:0;position:relative;z-index:2;
  -webkit-tap-highlight-color:transparent;
}

/* No focus BOX on the burger, ever.
   The browser's 2px outline draws a hard rectangle around the icon and stays
   painted after the menu closes. Live has the same rule but its outline resolves
   to black and disappears against the dark menu; ours inherits white and shows.
   Rather than leave keyboard users with no affordance, focus is indicated by
   thickening the three bars, which needs no box. */
.header-burger-btn:focus,
.header-burger-btn:focus-visible,
.header-burger-btn:active{outline:none!important;box-shadow:none!important;border:0!important}
.header-burger-btn:focus-visible .top-bun,
.header-burger-btn:focus-visible .patty,
.header-burger-btn:focus-visible .bottom-bun{height:2px}

/* Bar geometry measured off the live site: three 35x1 bars, absolutely
   positioned with top:0/bottom:0 so they centre in the box, then offset by
   exactly +/-9.5px. An earlier version used a short box with top/50%/bottom
   anchoring, which spread them unevenly and read as three separate lines. */
.header-burger-btn .burger-box{display:block;width:35px;height:35px;position:relative;margin:0 auto}
.header-burger-btn .burger-inner{display:block;width:100%;height:100%;position:relative}
.header-burger-btn .top-bun,
.header-burger-btn .patty,
.header-burger-btn .bottom-bun{
  position:absolute;top:0;bottom:0;left:0;margin-top:auto;margin-bottom:auto;
  width:100%;height:1px;background:currentColor;
  transition:transform .25s ease,opacity .2s ease;
}
.header-burger-btn .top-bun{transform:translateY(-9.5px)}
.header-burger-btn .patty{transform:none}
.header-burger-btn .bottom-bun{transform:translateY(9.5px)}

/* Open state: collapse to an X. */
.header--menu-open .header-burger-btn .top-bun{transform:rotate(45deg)}
.header--menu-open .header-burger-btn .patty{opacity:0}
.header--menu-open .header-burger-btn .bottom-bun{transform:rotate(-45deg)}

/* Panel. Scoped to .header--menu-open so it stays hidden by default. */
.header--menu-open .header-menu{
  opacity:1!important;visibility:visible!important;
  /* z-index 1, NOT 1001. The burger lives inside #header (z-index:10); a menu
     above that traps the whole header -- and therefore the X -- underneath the
     panel, so the close button was rendered, dark and correctly sized, yet
     painted behind the menu. Live uses menu:1 / header:10 for exactly this. */
  position:fixed;inset:0;z-index:1;
  /* overflow-x MUST be stated, and must be hidden.
     Declaring overflow-y alone is not a one-axis declaration: CSS computes a
     `visible` overflow-x to `auto` the moment the other axis is not visible.
     That silently turned the open overlay into a horizontal scroll container,
     and there is real geometry for it to scroll: every inactive folder panel
     is parked at translateX(100%), so scrollWidth measured 780 against a
     390 client width. A single drag swiped the whole menu off screen
     (scrollLeft 0 to 390 on an interior page, 285 on the homepage) and left
     the user staring at an empty panel with no way back but reload.
     hidden clips instead of scrolling, which is what the parked panels want
     anyway; the drill-in and Back slides are transforms and are unaffected. */
  overflow-x:hidden;overflow-y:auto;
  /* Belt and braces for the same failure: keep any residual horizontal
     gesture inside the overlay rather than handing it to the page behind. */
  overscroll-behavior-x:contain;
  background:var(--siteBackgroundColor,#fff);
}
.header--menu-open .header-menu-nav{visibility:visible!important}
.header--menu-open .header-menu-nav a{opacity:1!important}
body.header--menu-open{overflow:hidden}

/* Mobile menu panel: light, matching live.
   .header-menu-bg inherits theme-bg--primary, which resolves dark under the
   homepage's bright-inverse header, so the open menu came out black while live
   is light on every page. */
/* NOT scoped to .header--menu-open.
   Scoping the light background to the open state meant that the moment the
   class was removed the panel reverted to its dark theme-bg--primary value --
   while still fading out -- so dismissing the menu flashed black. The live site
   has this same flash; keeping the colours unconditional fixes it. The panel is
   visibility:hidden when closed, so an always-light background costs nothing. */
.header-menu-bg{background:#fafafa!important}
.header-menu,
.header-menu-nav,
.header-menu-nav a,
.header-menu-nav button{color:#1a1a1a!important}
/* The X itself.
   The bars take their colour from a bundle rule that resolves to the sand
   token (#dbd7ce), so setting only the button's `color` left an X that was
   technically rendered, correctly rotated, and invisible against the light
   menu. Live draws them black; state it on the bars directly. */
.header--menu-open .header-burger-btn{color:#1a1a1a!important}
.header--menu-open .header-burger-btn .top-bun,
.header--menu-open .header-burger-btn .patty,
.header--menu-open .header-burger-btn .bottom-bun{background:#1a1a1a!important}

/* Squarespace hides these labels; without the utility class they printed as
   visible text, so every dropdown read "Folder: Luxury Portfolio". */
.visually-hidden,
.header-menu .visually-hidden,
[hidden].visually-hidden{
  position:absolute!important;width:1px!important;height:1px!important;
  padding:0!important;margin:-1px!important;overflow:hidden!important;
  clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important;white-space:nowrap!important;border:0!important;
}

/* Only the active folder is on screen.
   !important is required: the component stylesheet sets display on
   .header-menu-nav-folder with higher specificity, so the plain class rule
   lost and the drilled-in submenu rendered as an empty panel. */
/* Sliding panels, matching live exactly.
   Every folder is absolutely positioned at inset:0. Inactive levels sit one
   screen to the right (translateX(100%)) and are visibility:hidden; the active
   one slides to 0; the level you came from slides out left (--open).
   display:none cannot animate, which is why an earlier version snapped. */
.header-menu .header-menu-nav-folder{
  position:absolute;top:0;left:0;right:0;bottom:0;
  display:flex!important;flex-direction:column;
  transform:translateX(100%);visibility:hidden;
  transition:transform .6s cubic-bezier(.4,0,.2,1),visibility 0s linear .6s;
  overflow-y:auto;will-change:transform;
}
/* TRANSFORM is deliberately NOT scoped to .header--menu-open.
   Live keeps the active folder at translateX(0) whether the menu is open or
   closed -- only inactive subfolders are parked one screen right. Scoping the
   transform meant that on dismiss the class stopped applying and the whole nav
   slid off to the right, so the menu "swiped away" where live fades it
   downwards. The downward fade is already correct and comes from two rules
   that were never the problem: .header-menu transitions opacity over 0.4s, and
   .header-menu-nav-list sits at translateY(20px) when closed. */
.header-menu .header-menu-nav-folder--active{
  transform:translateX(0)!important;
}
/* VISIBILITY still is scoped, and must stay that way. Unscoped, the closed
   menu's active folder kept visibility:visible, and since .header-menu is
   position:fixed;inset:0 the panel sat invisibly over the entire page and
   swallowed every click -- Read More links, cards, everything, at all widths.
   (.header-menu{pointer-events:none} below guards the same failure.) */
.header--menu-open .header-menu .header-menu-nav-folder--active{
  visibility:visible!important;
  transition:transform .6s cubic-bezier(.4,0,.2,1),visibility 0s;
}
/* Belt and braces: a closed menu must never take pointer events. */
.header-menu{pointer-events:none}
.header--menu-open .header-menu{pointer-events:auto}
/* The level you drilled in from exits to the left. */
.header-menu .header-menu-nav-folder--open{
  transform:translateX(-100%)!important;visibility:hidden;
}
@media (prefers-reduced-motion:reduce){
  .header-menu .header-menu-nav-folder{transition:none}
}

/* Only submenus contain a Back control (verified on live: root has none), so
   there is nothing to hide on inactive folders. An earlier rule did
   display:none on them, which fired the instant Back was clicked -- the control
   vanished and the panel reflowed while it was still sliding out, which read as
   the nav jumping. The panel now slides away intact. */
.header-menu-controls{display:flex;justify-content:center}

/* Folder chevron. Sits inline after the label. */
.header-menu-nav-item-content-folder{display:inline-flex;align-items:center;gap:.3rem}
.ea-folder-chevron{display:inline-flex;align-items:center;line-height:0}
/* This is the only cue that Luxury Portfolio, Neighborhoods and Calculators
   open a submenu instead of navigating, so it has to be legible. It was not.
   Three things were wrong at once and none of them were visible in a diff:

   1. COLOUR. Nothing here won. The rule that actually applied was the bundle's
      `.header--menu-open .header .header-dropdown-icon svg`, specificity
      (0,3,1) against the (0,1,1) written below it, and it paints from
      --menuOverlayNavigationLinkColor. Under the header's bright-inverse
      section theme that token resolves to the sand token #dbd7ce, which on the
      #fafafa menu ground measured a contrast ratio of 1.38:1. Exactly the
      failure the burger bars hit above, from exactly the same token.
      --eabc-muted over the same ground measures 5.26:1: legible on any screen,
      still visibly lighter than the #1a1a1a label beside it (15.9:1), so it
      stays a hint rather than a second control.

   2. WEIGHT. #openArrowHead is `M18 7L11 14L4 7` with fill="none": a
      stroke-only glyph, not the filled one the old comment here described. A
      presentation attribute beats an inherited value, so `fill:currentColor`
      never drew anything and the whole mark was a 0.5 user-unit hairline. It
      is stated as a stroke now, at a weight that survives the smaller size.

   3. SIZE. `width:1em` lost to `:not(.header--menu-open) .header-dropdown-icon
      svg{width:100%;height:100%}` at (0,2,1), so the box fell back to the 33px
      attribute runtime.js writes. That happened to match the old 33px type by
      coincidence; against the new 21.8px it would have been half again taller
      than its own label. The selector below now carries the class twice to
      clear both bundle rules without !important, and .8em keeps the glyph
      proportional to whatever the clamp resolves to.

   Rotation is unchanged and deliberate: the sprite arrowhead points DOWN,
   shared with the desktop dropdowns, and -90deg is what turns it into a
   right-pointing drill-in marker. Unrotated it reads as a diagonal slash.
   The Back control carries no chevron of its own, so none of this reaches it. */
.header-menu .header-dropdown-icon.ea-folder-chevron svg{
  width:.8em;height:.8em;transform:rotate(-90deg);
  fill:none;
  stroke:var(--eabc-muted,rgba(0,0,0,.58));
  stroke-width:2px;stroke-linecap:round;stroke-linejoin:round;
}

/* Applied only while the menu is being reset to root on open, so that snap
   back is instant instead of sliding into view. */
.header-menu.ea-menu-no-anim .header-menu-nav-folder{transition:none!important}

/* Mobile menu type scale.

   The ported Squarespace scale sets `.header-menu-nav-item a{font-size:8.5vmin}`
   in sqs-site.css (6.6vmin from 576px, 6vmin from 768px). At 390 that resolves
   to 33.15px, which is page-heading size: the site's own h2 measures 30.2px on
   the homepage. Eight items at that size occupied 131px to 590px of an 844px
   screen, so the menu read as a stack of headlines rather than as navigation.

   Two separate things were wrong and they are fixed separately.

   TYPE comes down to clamp(19px, 5.6vmin, 24px), which is 21.8px at 390. That
   sits clearly under the h2 and clearly over the 16px Hanken Grotesk phone
   number below it, so the closing group still reads as secondary to the nav.
   The clamp also caps the size on coarse-pointer tablets, where vmin is the
   768px edge and the unclamped 6vmin blew the items up to 46px.

   TAP TARGET goes the other way. The old items were only 33px of touchable
   height with 24px of dead space between them, so the thing being tapped was
   smaller than the thing being read. min-height gives every link the 44px both
   platforms ask for, and the padding keeps that true if the clamp lands high.
   Because the box now carries its own height, the 3.1vw (12px) vertical margin
   is cut to 4px: pitch drops from 57px to 52px per row while the touchable
   area grows from 33px to 44px.

   Scoped to the query that decides the burger exists at all, the same one
   .ea-menu-tel is gated to. The overlay is in the DOM at every width, so an
   unscoped rule would restyle a panel desktop users can never open. The
   selector carries the extra .header-menu class purely to outrank the three
   bundle rules without reaching for !important.

   The chevron on the folder items is sized in em by .ea-folder-chevron svg, so
   it follows the type down and stays optically attached to the label. */
@media only screen and (pointer:coarse) and (max-width:1024px), screen and (max-width:799px){
  .header-menu .header-menu-nav-item a{
    font-size:clamp(19px,5.6vmin,24px);
    min-height:44px;
    margin:4px 5vw;
    padding:.35rem 0;
    box-sizing:border-box;
  }
}

/* Call the firm, from the foot of the mobile menu.

   Styled as a label rather than as another nav destination: Hanken Grotesk at
   label size and letter-spaced, against the EB Garamond the nav items are set
   in, so it reads as a way to reach the firm and not as a ninth page. Colour
   comes from the menu's own `.header-menu-nav a` rule, so it stays with the
   nav items rather than importing a colour from elsewhere.

   Display is gated to the SAME query Squarespace uses for
   .header-display-mobile, which is the query that decides the burger exists at
   all. The overlay is in the DOM on every page at every width, so without the
   gate the number would sit in the markup at desktop widths too.

   min-height on the anchor, not the row, because the row is the full menu
   width: the 44px belongs to the thing being tapped.

   No bottom margin: this block sits directly on top of .header-menu-actions,
   and the two are meant to read as one closing group. The 44px tap box already
   carries 14px of padding under the digits and the social row carries its own
   15px above the icons, so the pair land about 29px apart without adding a
   margin that would split them into two stacked blocks. The social row keeps
   its own 6vw bottom margin, and is not touched. */
.ea-menu-tel{display:none}
@media only screen and (pointer:coarse) and (max-width:1024px), screen and (max-width:799px){
  .ea-menu-tel{
    display:flex;justify-content:center;
    width:100%;box-sizing:border-box;flex-grow:0;flex-shrink:0;
    padding-left:var(--pagePadding,1.5rem);padding-right:var(--pagePadding,1.5rem);
    margin:0;
  }
}
.ea-menu-tel a{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:0 1rem;
  font-family:var(--primary-button-font-font-family,"Hanken Grotesk"),system-ui,sans-serif;
  font-size:1rem;font-weight:400;line-height:1;letter-spacing:.12em;
  text-decoration:none;
}
.ea-menu-tel a:focus-visible{outline:2px solid currentColor;outline-offset:4px}

/* ---------------------------------------------------------------------------
   Footer corrections.

   Both of these exist on the live site and were reproduced faithfully by the
   port; they are content-entry defects rather than design choices, so they are
   corrected here rather than replicated.
   --------------------------------------------------------------------------- */

/* 1. The brand line's block is authored to span grid rows 7-11 while the
      copyright sits in row 10, so the two print on top of each other. Let the
      brand block end before the copyright row. */
footer .fe-block-b9b641b3734c71ff54f9{grid-row-end:10!important}
footer .fe-block-26878e97aebda7a543a0{grid-row-start:10!important;grid-row-end:12!important}

/* 2. "Neighborhoods" was authored inside a sqsrte-text-highlight span while its
      siblings sit in sqsrte-small, so it alone lost the underline. */
footer .sqsrte-text-highlight a,
footer a.sqsrte-text-highlight{text-decoration:underline!important}

/* Team grid.
   Placement is Fluid Engine's job -- the shortcode emits real .fluid-engine /
   .fe-block markup with live's grid-area values, so the ported bundle CSS puts
   the cards at x=156/551/946 by itself. Only the inside of a block is styled
   here.

   Sizes are the measured live values rather than round numbers: 24.574/31.946
   for the name and 21.144/27.488 for the detail lines, both EB Garamond 400 at
   0.2114px tracking. The 16px paragraph margins are live's too, and they
   collapse between adjacent lines to give the 43px rhythm. */
.ea-team-section .fe-block > .sqs-block{display:flex;height:100%;width:100%}
.ea-team-section .fe-block > .sqs-block > .sqs-block-content{width:100%}

/* The headshot is taken out of flow on purpose.
   Fluid Engine rows are minmax(row-height, auto), so an in-flow image taller
   than its 7 rows grows them: the non-square source photos came out 231px and
   302px tall against everyone else's 271px. Absolutely positioning the image
   means it contributes no height, the rows sit at their minimum, and every
   block resolves to the same 271x268 live uses. */
.ea-team-section .fe-block > .sqs-block{position:relative}
.ea-team-img{position:absolute;inset:0;overflow:hidden}
.ea-team-img a{display:block;width:100%;height:100%}
.ea-team-img img{width:100%;height:100%;object-fit:cover;object-position:50% 50%;display:block}

.ea-team-name p{margin:0;font-family:"EB Garamond",Garamond,Georgia,serif;
  font-size:24.574px;line-height:31.9462px;font-weight:400;letter-spacing:.211444px;color:#000}
.ea-team-meta p{margin:16px 0;font-family:"EB Garamond",Garamond,Georgia,serif;
  font-size:21.1444px;line-height:27.4877px;font-weight:400;letter-spacing:.211444px;color:#000}
.ea-team-meta p:first-child{margin-top:0}
.ea-team-meta p:last-child{margin-bottom:0}
.ea-team-meta em{font-style:italic}
.ea-team-name a,.ea-team-meta a{color:inherit;text-decoration:underline}

@media (max-width:767px){
  .ea-team-name p{font-size:21.4px;line-height:27.82px}
  .ea-team-meta p{font-size:18.4px;line-height:23.92px;margin:14px 0}
}

/* Screen-reader-only archive H1 (see archive.php). Standard clip technique --
   must not use display:none, which removes it from the accessibility tree and
   from the heading outline entirely. */
.ea-visually-hidden{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* Listing heading + intro, for the two archives that have one on live.
   Values measured off live at 1440px: Cormorant Garamond 45.376/50.7485 for the
   heading, EB Garamond 21.184/27.5392 for the intro, heading 50px clear of the
   header and the paragraph 46px below it, intro column 558px wide. */
/* Also used by /press, which is the same thing wearing a different post type:
   a page whose whole body is a grid of cards. Its heading lives in the page
   body rather than in a template (scripts/add_press_heading.php), so this rule
   has one consumer that is not archive.php -- grep before changing it. */
/* margin, NOT padding: runtime.js sets an inline padding-top on this block
   equal to the header height, so a padding-top here is overridden. */
.ea-archive-intro{margin:50px auto 3.2rem;text-align:center;max-width:1012px}
.ea-archive-intro h1{font-family:"Cormorant Garamond",var(--heading-font-font-family),Georgia,serif;
  font-weight:400;font-size:45.376px;line-height:50.7485px;margin:0 0 46px}
.ea-archive-intro p{font-family:"EB Garamond",var(--body-font-font-family),Georgia,serif;
  font-size:21.184px;line-height:27.5392px;margin:0 auto;max-width:558px}

/* THE ARCHIVE CALL TO ACTION, one rule for every listing that carries one.
   /buildings and /neighborhoods both have it and they sit side by side in the
   nav, so it is defined here beside .ea-archive-intro rather than twice in the
   two per-page stylesheets, where the pair would drift the first time either
   was touched. Each page supplies its own label; nothing else differs.

   Zeve, on the small underlined hand-off line this first shipped as: "why
   would the CTA be tiny text instead of the big buttons we have". So it is
   .eabc-btn at full size with no re-skin, which is why there is no type,
   colour or padding below: the button brings its own, including the hover
   convention of the plate stepping one shade darker with the label unchanged.
   The only job here is placement.

   The selector names .ea-archive-intro because `.ea-archive-intro p` above
   carries a type and would otherwise win, wrapping the button in 27.5392px of
   EB Garamond leading. Two classes beat one class and a type, which is
   cheaper than an !important. */
.ea-archive-intro .ea-archive-cta{max-width:none;margin:1.8rem auto 0;text-align:center;
  font-size:1rem;line-height:1}
.ea-archive-cta .eabc-btn{margin:0}

/* The enquiry card at the foot of a listing.
   .ea-autocta carries margin-top:3rem for the article pages it was built for,
   where it follows body copy that ends on its own last line. After a listing
   it follows a FIELD that already ends on its own bottom padding, 88px at 1440
   and 56px at 390, and the two compounded: Zeve, on /buildings, "too much
   white space above the form". Measured 152px at 1440 and 120px at 390 from
   the last card to the top of the sand card. Zeroed here so the field's own
   padding is the whole gap, which puts it on 88 / 56, the same step the
   homepage Contact band uses for exactly the same job. */
/* AND THE SAME AGAIN UNDERNEATH. Fixing only the top left the card sitting in
   88px of space above and 16px below it, because .ea-autocta's own bottom
   margin is 1rem: enough after body copy on an article, nothing like enough
   under a card that is the last thing on the page before the footer. Zeve,
   looking at the result: "the white space above and below the form on the
   /buildings/ root page still does not match."

   Both numbers now come from the same place. The field above ends on 5.5rem of
   its own padding (3.5rem below 767px, set in each archive's stylesheet), so
   the card takes the identical step underneath and the gap reads as one
   measure rather than as two unrelated ones. Change the field padding and this
   has to change with it, which is why the values are written here together. */
/* .ea-tx, the /notable-transactions field, is the third listing to carry the
   card and it ends on the identical 5.5rem / 3.5rem padding, so it takes the
   identical treatment rather than a fourth number. */
/* .ea-txs-related is the last block on a single transaction page. It ends on
   its own padding the same way a listing field does, so the card takes the same
   treatment rather than a fifth number. See
   assets/css/transaction-single.css, which deliberately sets none of this.

   .ea-txs-nav, the prev/next strip, used to sit between the two and carried the
   same rule. Zeve took it out: "the 'next' and 'previous' should be removed
   since the bottom of page changed." Its selector came out of this list with
   it, so nothing here matches an element that no longer exists. */
.ea-bidx + .ea-autocta,
.ea-nbhd + .ea-autocta,
.ea-tx + .ea-autocta,
.ea-txs-related + .ea-autocta{margin-top:0;margin-bottom:5.5rem}

@media (max-width:767px){
  .ea-bidx + .ea-autocta,
  .ea-nbhd + .ea-autocta,
  .ea-tx + .ea-autocta,
  .ea-txs-related + .ea-autocta{margin-bottom:3.5rem}
}

@media (max-width:767px){
  .ea-archive-intro{margin-top:24px}
  .ea-archive-intro h1{font-size:32px;line-height:1.14;margin-bottom:24px}
  .ea-archive-intro p{font-size:18.4px;line-height:1.45}
  /* The button is NOT shrunk, only pulled a step closer to the intro: at 390 a
     51.6px pill plus its clearance is the difference between the first card
     showing below the fold and not showing at all, and the clearance is the
     half of that pair that is not the control. */
  .ea-archive-intro .ea-archive-cta{margin-top:1.3rem}
}

/* Portfolio cards are title-only; drop the gap the meta block used to hold. */
.ea-card-bare .blog-title{margin-top:.9rem}

/* Site background.
   Live paints the page #fafafa, not white -- the warm off-white ("greige") that
   shows above and around every section, including behind the overlay header.
   The ported bundles default `body` to #fff, so every page here was a shade
   too bright. Squarespace drives this from --siteBackgroundColor, so define the
   token rather than hardcoding the colour at each use. */
:root{--siteBackgroundColor:#fafafa}
body{background-color:var(--siteBackgroundColor)}

/* Listing theme band.
   Reproduces the first section's `.section-background` on the custom listing
   templates. Full width of .content (which is already the full viewport on
   these pages) rather than 100vw, which would add a horizontal scrollbar once
   a vertical one is present. The intro sits above it on z-index. */
.ea-archive-hero{position:relative;width:100%;padding-bottom:44px}
.ea-archive-hero>.section-background{position:absolute;inset:0;z-index:0;
  background-color:var(--siteBackgroundColor,#fafafa)}
.ea-archive-hero>.ea-archive-intro,
.ea-archive-hero>.ea-visually-hidden{position:relative;z-index:1}

/* Homepage hero, second line.
   The hero reads "Your Real Estate / Family Office" but Squarespace authored it
   as two separate Fluid Engine blocks, each an <h1>, giving the homepage two
   h1s for one phrase. They sit in different grid cells so they cannot be
   merged; the second is a paragraph instead, restyled to the exact h1 metrics
   measured on the rendered page so nothing moves. */
.ea-hero-line{font-family:"Cormorant Garamond",var(--heading-font-font-family),Georgia,serif;
  font-size:45.376px;line-height:50.7485px;font-weight:400;letter-spacing:.45376px;margin:0}

/* "Inquire" now jumps to the building's own form further down the same page.
   The header is a fixed overlay, so without scroll-margin the anchor lands
   underneath it and the form heading is hidden. --ea-header-height is set by
   runtime.js from the measured header; the literal is the desktop fallback. */
#ea-blog-cta{scroll-margin-top:calc(var(--ea-header-height, 128px) + 24px)}
/* Deliberately NO global `scroll-behavior:smooth`. It animates every
   programmatic scroll on the site, not just this anchor, and on the long
   building pages that was enough to stall scripted scrolling outright.
   scroll-margin-top is what actually makes the anchor land correctly. */

/* The homepage contact section's Fluid Engine row overrides USED TO LIVE HERE.
   They are gone because the thing they were propping up is gone.

   The section was imported Squarespace markup: a Fluid Engine grid whose form
   block reserved 13 rows (510px) to fit the Squarespace form live runs, while
   the Tally embed that replaced it renders at 313px. Two rules clamped the
   section to 12 rows and the form block to 9 so the leftover ~260px of white
   closed up. That was treating the symptom; the section still had its heading
   floating centred over an empty left third, which is what got it called ugly
   and out of place.

   It is now [elevated_home_contact], rendered from inc/home-contact.php and
   styled in assets/css/home-sections.css, in flow rather than on a grid, so
   there are no rows to clamp. Neither .fe-685dee4b7da7ed3458cd590a nor
   .fe-block-39ea19da1a662d52f11d exists in the document any more; the rules
   were dead selectors and a misleading description of a section that no longer
   works that way. scripts/rebuild_home_contact.php did the replacement and can
   undo it, and the original markup is on page 113's
   `_elevated_home_contact_legacy` meta key. If it is ever reverted, restore
   these two rules with it. */

/* ---------------------------------------------------------------------------
   Market Watch stat section.

   Type comes from the site's own scale: Cormorant Garamond for the numerals
   (matching the hero and section headings), Hanken Grotesk letterspaced small
   caps for labels (matching .eabc-eyebrow). Greige ground is --eabc-sand, the
   same band the header sits on elsewhere, so it reads as part of the site
   rather than a widget dropped into it.
   --------------------------------------------------------------------------- */
.ea-mw{background:var(--eabc-sand,#dbd7ce);padding:5.5rem 6vw;color:var(--eabc-ink,#2e2e2f)}
.ea-mw__inner{max-width:1012px;margin:0 auto;text-align:center}

.ea-mw__eyebrow{margin:0 0 1.1rem;font-family:var(--primary-button-font-font-family,"Hanken Grotesk"),system-ui,sans-serif;
  font-size:.75rem;text-transform:uppercase;letter-spacing:.16em;color:var(--eabc-muted,rgba(0,0,0,.58))}
.ea-mw__title{margin:0 0 .5rem;font-family:"Cormorant Garamond",var(--heading-font-font-family),Georgia,serif;
  font-weight:400;font-size:2.4rem;line-height:1.15}
.ea-mw__title a{color:inherit;text-decoration:none}
.ea-mw__title a:hover{text-decoration:underline}
.ea-mw__week{margin:0 0 3.2rem;font-family:"EB Garamond",var(--body-font-font-family),Georgia,serif;
  font-size:1.05rem;font-style:italic;color:var(--eabc-muted,rgba(0,0,0,.58))}
.ea-mw__week a{color:inherit;text-decoration:none}
.ea-mw__week a:hover{text-decoration:underline}

/* Stats. A <dl>, so the label/value pairing survives without CSS. */
.ea-mw__stats{display:grid;grid-template-columns:repeat(3,1fr);gap:2.5rem;margin:0 0 3.5rem}
.ea-mw__stat{margin:0}
.ea-mw__stat-label{font-family:var(--primary-button-font-font-family,"Hanken Grotesk"),system-ui,sans-serif;
  font-size:.72rem;text-transform:uppercase;letter-spacing:.16em;color:var(--eabc-muted,rgba(0,0,0,.58));margin:0 0 .6rem}
/* dd carries a default 40px indent in every UA stylesheet; without this the
   numbers sit off-centre under their labels. */
.ea-mw__stat-value{margin:0;font-family:"Cormorant Garamond",var(--heading-font-font-family),Georgia,serif;
  font-weight:400;font-size:clamp(2.6rem,5vw,4rem);line-height:1;letter-spacing:-.01em}
.ea-mw__stat-note{margin:.55rem 0 0;font-family:"EB Garamond",var(--body-font-font-family),Georgia,serif;
  font-size:.92rem;color:var(--eabc-muted,rgba(0,0,0,.58))}

/* Trend bars. Plain divs, no chart library: the accessible name on the
   container carries every value, so the shape is decoration over real data. */
.ea-mw__chart{margin:0 0 3rem}
.ea-mw__chart-cap{font-family:var(--primary-button-font-font-family,"Hanken Grotesk"),system-ui,sans-serif;
  font-size:.7rem;text-transform:uppercase;letter-spacing:.14em;color:var(--eabc-muted,rgba(0,0,0,.58));margin:0 0 1rem}
.ea-mw__bars{display:flex;align-items:flex-end;justify-content:center;gap:.5rem;height:110px}
.ea-mw__bar{flex:0 1 34px;background:var(--eabc-ink,#2e2e2f);opacity:.32;min-height:3px;border-radius:1px}
.ea-mw__bar:last-child{opacity:.85}

.ea-mw__cta{margin:0}

/* The section label is also the way to the archive it names. Underline on hover
   only, exactly like .ea-mw__title a and .ea-mw__week a above, so it stays a
   label at rest and adds no height to the line either way. */
.ea-mw__eyebrow a{color:inherit;text-decoration:none}
.ea-mw__eyebrow a:hover{text-decoration:underline}
.ea-mw__eyebrow a:focus-visible{outline:2px solid var(--eabc-ink,#2e2e2f);outline-offset:3px}

/* The secondary way out, under the button. Deliberately NOT a second .eabc-btn:
   two dark pills in a column compete, and the button above is the one that
   should win. Hairline under the words, the same device the week line uses. */
.ea-mw__archive{margin:1.1rem 0 0;font-family:var(--primary-button-font-font-family,"Hanken Grotesk"),system-ui,sans-serif;
  font-size:.85rem;letter-spacing:.02em}
.ea-mw__archive a{color:var(--eabc-ink,#2e2e2f);text-decoration:none;border-bottom:1px solid rgba(46,46,47,.28)}
.ea-mw__archive a:hover,.ea-mw__archive a:focus-visible{border-bottom-color:var(--eabc-ink,#2e2e2f);text-decoration:none}
.ea-mw__archive a:focus-visible{outline:2px solid var(--eabc-ink,#2e2e2f);outline-offset:3px}

@media (max-width:767px){
  .ea-mw{padding:3.5rem 6vw}
  .ea-mw__title{font-size:1.75rem}
  .ea-mw__week{margin-bottom:2.2rem}
  .ea-mw__stats{grid-template-columns:1fr;gap:2rem;margin-bottom:2.5rem}
  .ea-mw__stat-value{font-size:2.8rem}

  /* THE HOMEPAGE BAND'S THREE TILES TURN ON THEIR SIDE ON A PHONE.

     Measured at 390 before this rule: the three stacked tiles took 385px, which
     is 39 percent of a 985px band, to carry nine short lines. Worse, every line
     was centred, so the three figures shared no edge at all: "18", "$135.5M"
     and "$24M" render 36px, 130px and 92px wide, which put their right edges
     190px, 236px and 218px from the left of a 343px column. Three numbers whose
     whole job is to be read against each other, and not one of them lined up
     with another. That is the same arithmetic that put the /home2 opening's
     four figures two up rather than stacked.

     THREE ACROSS WAS MEASURED AND REJECTED. The binding width here is not the
     figure, it is the label. "CONTRACTS SIGNED" is 139px at .72rem with .16em
     tracking, and a third of a 343px column is 106px, so all three labels and
     two of the three notes would wrap, at different points, and the tiles would
     stop lining up with each other in the other direction instead. At 320 the
     column is 85px and nothing survives it.

     So the tile turns sideways rather than shrinking. The label and its note
     take the left, the figure takes the right, and the figure sits in vertical
     space the label and the note were already spending: 224px for the same nine
     lines, and the three figures end on one edge. 2.4rem, not the 2.8rem the
     centred stack used, because "$135.5M" is 111px at 2.4rem and the widest
     label is 139px, which still leaves 16px of slack in a 320px column, so
     nothing wraps at any width the audit checks.

     The rule is the 1px rgba(0,0,0,.16) hairline .ea-kc__card uses where there
     is no photograph to carry a card, drawn as a DIVIDER: see THE HAIRLINE RULE
     at the top of this file. One column, so N is 1 and only Contracts Signed
     loses its rule, and nothing closes the foot of the list. No new colour, face
     or spacing step.

     THIS BLOCK USED TO CLOSE AT THE BOTTOM, copied from .ea-hcontact__item and
     .ea-contact__item, on the argument that the three figures would otherwise
     trail off into the chart. Zeve rejected that treatment on those two lists
     and on .ea-hood__item, and it goes from here with them, for three reasons.
     It is the same construction, copied from a source that is no longer built
     that way. The contact rail and these tiles are BOTH on the homepage at 390
     and four sections apart, so one boxed list and one divided list is an
     inconsistency in a single scroll. And the argument does not survive the
     render: what makes the three read as a set is the shared column edge, the
     labels ranged left against figures ranged right, and the two rules between
     them, none of which the cap and the foot were contributing to. The chart is
     already held off by 2.6rem and by its own eyebrow caption.

     SCOPED TO .ea-mw, the shortcode's own section, and not to .ea-mw__stats.
     That class is also the /market-watch index hero's, twice, and the report
     pages' context panel (.ea-mw__stats.ea-mwx__figs), and both of those have
     their own measured mobile rules in market-watch.css and mw-chart.css.
     Widening this to the bare class would silently reshape four other places.

     DOM ORDER IS UNTOUCHED. The <dl> still emits label, figure, note in that
     order, so a screen reader still hears "Contracts Signed, 18, above $4
     million". Only the grid placement differs, and nothing in a tile takes
     focus, so there is no tab order to disagree with. */
  .ea-mw .ea-mw__stats{gap:0;margin-bottom:2.6rem;text-align:left}
  .ea-mw .ea-mw__stat{display:grid;grid-template-columns:minmax(0,1fr) auto;
    align-items:center;column-gap:1rem;padding:1.1rem 0;
    border-top:1px solid rgba(0,0,0,.16)}
  .ea-mw .ea-mw__stat:first-child{border-top:0}
  .ea-mw .ea-mw__stat-label{grid-column:1;grid-row:1;margin:0;line-height:1.3;
    text-align:left;overflow-wrap:break-word}
  .ea-mw .ea-mw__stat-note{grid-column:1;grid-row:2;margin:.25rem 0 0;
    line-height:1.35;text-align:left;overflow-wrap:break-word}
  .ea-mw .ea-mw__stat-value{grid-column:2;grid-row:1 / span 2;margin:0;
    font-size:2.4rem;line-height:1;text-align:right}
}

/* ---------------------------------------------------------------------------
   /calculators index block.

   style.css carries a `* { box-sizing: border-box }` reset that live does not
   have. The ported code block sizes itself `max-width:880px; padding:0 1rem`,
   which Squarespace resolves as content-box, so under the reset the whole
   column rendered 32px narrower than live (848px vs 880px at 1440).

   Scoped to the block's own id rather than relaxing the global reset: that
   reset is load-bearing for the rest of the build and this is the only place
   the difference is measurable. #id beats `*`, so no !important is needed.
   --------------------------------------------------------------------------- */

/* ===========================================================================
   Homepage: tablet-band (roughly 576-1200px) layout repairs.

   All three problems below only appear once the window is narrower than a
   desktop but still on the Fluid Engine *desktop* grid (>=768px), which is the
   one width band nobody had measured. Everything here is scoped to that band
   or to the specific block, so 390px and 1440px are untouched.
   =========================================================================== */

/* 1. Hero second line ("Family Office").
   The line above it is a real <h1> and Squarespace sizes h1 fluidly:
     min(calc((--heading-1-size-value - 1) * 1.2vw + 1rem), max(...))
   so it shrinks from 45.376px at 1440 to 34.36px at 900. The ported
   .ea-hero-line above was measured once at 1440 and hardcoded, so at every
   width below 1440 the two halves of one phrase rendered at different sizes --
   34.36px over 45.376px at 900px wide. Restate the *formula* rather than a number, in
   the same two media queries Squarespace uses, so the paragraph tracks the h1
   at every width by construction. Live has both halves as h1 and they always
   match; this reproduces that without reintroducing the second h1. */
@media screen and (max-width:767px) and (orientation:portrait){
  .ea-hero-line{font-size:calc((var(--heading-1-size-value) - 1) * calc(.012 * min(100vh, 900px)) + 1rem)}
}
@media screen and (min-width:768px),screen and (orientation:landscape){
  .ea-hero-line{font-size:min(calc((var(--heading-1-size-value) - 1) * 1.2vw + 1rem),
    max(calc((var(--heading-1-size-value) - 1) * 0.012 * var(--maxPageWidth) + 1rem),
        calc(var(--heading-1-size-value) * 1rem)))}
}
/* Same source as the h1 rule in the bundle, so the two lines stay locked. */
.ea-hero-line{line-height:calc(var(--heading-font-line-height) * (1 + (1 - var(--heading-1-size-value))/25));
  letter-spacing:var(--heading-font-letter-spacing)}

/* 2. "LUXURY PORTFOLIO" button glued to the paragraph above it.
   The two Fluid Engine blocks overlap by design: the paragraph holds rows
   16-21 and the button rows 20-23. On desktop the paragraph is short enough to
   sit inside its rows; between 768px and ~1150px it wraps to five lines, is
   ~44px taller than its five rows, and -- being centre-aligned in its area --
   bleeds ~22px past the bottom of them, straight into the button. Measured
   clearance from the last line of text to the top of the button:
     768px -9px | 860px -8px | 900px -2px | 960px 0px | 1024px +4px
   against +50px at 390px and +56px at 1440px. (Live is identical here; its
   larger numbers in a headless browser are the .preSlide reveal transform,
   translateY(16.5px), not layout.)
   Fixing it on the button block rather than the paragraph keeps the paragraph
   exactly where live puts it. A margin on the grid item shifts it down by the
   full amount, and the row is minmax(rowHeight, auto) so the track absorbs it.
   The min()/max() pair holds the correction at 45px up to ~1155px and then
   tapers it to nothing by 1200px, where the natural clearance has recovered,
   so there is no step where the band ends. Roughly half of each pixel of
   margin is absorbed by the shared rows 20-21 growing (which re-centres the
   paragraph slightly lower), hence 45px to buy ~30px of clearance. */
@media (min-width:768px) and (max-width:1199.98px){
  .fe-block-3b5264a2ecf516c9f9f3{
    margin-top:min(45px, max(0px, calc(1200px - 100vw)))!important;
  }
}

/* 3. Press logo strip: only two logos, and no way to reach the other eight.
   The carousel is 10 logos with data-navigation-controls="none", so the only
   affordance the markup carries is .mobile-arrows -- which the bundle reveals
   at <=575px and hides everywhere above. Combined with runtime.js pinning the
   carousel to two slides for the whole 640-1023px range, the band showed two
   440px-wide logos and nothing else: no arrows, no scrollbar (the strip does
   scroll, but .user-items-list-carousel__slides hides its scrollbar), no hint
   that eight more existed. Live behaves the same way, so there is nothing to
   copy; the fix is to reuse the arrow control the build already renders and
   styles correctly at 390px. Slide count is handled in runtime.js.
   Capped at 1023px so the >=1024px and 1440px layouts are untouched. */
/* Scoped to the press section rather than to .user-items-list-carousel at
   large, so this stays a fix for one section and not a site-wide change to
   every carousel the build might grow later. */
@media (min-width:576px) and (max-width:1023.98px){
  [data-section-id="681f72a3b02c203237dabec7"] .user-items-list-carousel .mobile-arrows{
    display:flex!important;position:static!important;justify-content:center;margin-top:20px}
  [data-section-id="681f72a3b02c203237dabec7"] .user-items-list-carousel .desktop-arrows{
    display:none!important}
}

/* ===========================================================================
   Homepage hero: never break "Your Real Estate" or "Family Office" mid-phrase.

   The hero is one phrase in two Fluid Engine blocks, both centred on the same
   six grid columns (11/17 of 26): the <h1> "Your Real Estate" on rows 5-7 and
   the .ea-hero-line paragraph "Family Office" on rows 7-9.

   Why it broke: the cell is a fixed share of the viewport (6/24 of the content
   grid, about 0.228 * 100vw) but Squarespace's fluid h1 size is
   `(--heading-1-size-value - 1) * 1.2vw + 1rem`, i.e. a slope PLUS a 16px
   constant. Type therefore shrinks more slowly than the cell it sits in, so
   below a crossover width the line no longer fits and re-wraps mid-phrase.
   Measured crossovers on the desktop grid: the h1 wrapped to "Your Real /
   Estate" from 1130px down, and "Family Office" wrapped from 772px down, to
   the 768px breakpoint where the mobile grid (a full-width cell) takes over
   and both fit again. Live has the same bug; this deliberately diverges.

   Fix: forbid the break rather than shrink the type, so the rendered size
   still matches live at every width. Alternatives rejected: `text-wrap:
   balance`/`pretty` only rebalance an already-wrapping line, they cannot hold
   one line; a non-breaking space would mean editing post_content; capping the
   font size to the cell would have shrunk the hero ~17% across the whole
   768-1130 band.

   `!important` is required: both elements carry an inline `white-space:
   pre-wrap` from the Squarespace export. The h1 is matched through its
   Fluid Engine block id because the homepage h1 carries no class of its own;
   note .ea-hero-title is NOT this element, it is the heading on the 50
   building pages, so it is deliberately not in the selector.

   The block must also be allowed to *be* as wide as its unbroken line, hence
   width:max-content + justify-self:center on the two grid items. Left at the
   cell width, Blink does not centre an overflowing line: it pins it to the
   start edge and spills right only, which pushed the h1 up to 17px right of
   the paragraph below it in the 768-1130 band. Sizing the item to its content
   and centring the item instead keeps both halves concentric, measured dead
   on the viewport centre at every width. min-width:0 is belt and braces so
   the item's content-based automatic minimum can never feed back into track
   sizing.

   Overflow safety: with nowrap the widest the hero ever gets is 299px (at
   1440) and 226px (mobile, where the size is vh-based and constant), against
   a 360px minimum viewport, so it cannot reach the edge. Verified: zero
   horizontal overflow and both halves on one line at every 20px step from
   1440 to 360, plus 767/768/769 either side of the grid breakpoint. No type
   was shrunk; computed font-size still matches live at every width.
   =========================================================================== */
.fe-block-6832cb6330c13ae0ddae h1,
.ea-hero-line{white-space:nowrap!important}
.fe-block-6832cb6330c13ae0ddae,
.fe-block-2c47e9cdf08b9c4d7fc7{width:max-content;min-width:0;justify-self:center}

/* Search form on the results page. Uses the site's own button; only the input
   needs styling, and it borrows the archive intro's type. */
.ea-search-form{display:flex;gap:.6rem;justify-content:center;margin:1.6rem auto 0;max-width:520px}
.ea-search-form input[type=search]{flex:1 1 auto;min-width:0;padding:.85rem 1rem;
  font-family:"EB Garamond",var(--body-font-font-family),Georgia,serif;font-size:1rem;
  border:1px solid rgba(0,0,0,.25);border-radius:6.4px;background:#fff;color:var(--eabc-ink,#2e2e2f)}
.ea-search-form .eabc-btn{padding:.85rem 1.4rem;white-space:nowrap}
@media (max-width:520px){.ea-search-form{flex-direction:column}}

/* Calculators index: the ported code block sizes itself max-width + padding,
   which Squarespace resolves as content-box. The theme's global border-box
   reset made it 32px narrower than live. Scoped so the reset stays intact
   everywhere else. #id beats *, so no !important. */
#ea-calc-index { box-sizing: content-box; }

/* ===========================================================================
   Press logos: a continuous strip rather than a paged carousel.

   Ten logos, all the same kind of object, and no reason to page through them a
   screenful at a time. runtime.js duplicates the strip once and sets
   the scroll distance to the width of exactly one copy, so when the animation
   reaches that offset the second copy sits precisely where the first started
   and the reset is invisible. Duration is derived from that width, so the
   logos move at a constant speed instead of a constant lap time.

   Scoped by section id, matching the tablet arrow fix above: a carousel added
   elsewhere later keeps the paged behaviour.
   =========================================================================== */
/* The animation itself lives in runtime.js, not here. A CSS keyframe has to
   read the scroll distance from a custom property, and a transform built from
   calc() over a var() cannot be resolved ahead of time, so Chrome refuses to
   composite it and runs the whole thing on the main thread. That is what made
   the first version stutter. Concrete values through the Web Animations API
   composite; hover and focus pausing moved to script along with it. */

/* Arrows page a carousel; there are no pages here. Placed after the tablet
   arrow rule above so it wins on source order at equal specificity. */
[data-section-id="681f72a3b02c203237dabec7"][data-ea-ticker-on] .mobile-arrows,
[data-section-id="681f72a3b02c203237dabec7"][data-ea-ticker-on] .desktop-arrows{
  display:none!important
}

/* Each logo is a link to /press. runtime.js wraps the media box in an
   .ea-press-link, which is why this is scoped by section id and not by class
   alone: the class only ever exists here, but the id says so out loud.

   display:block is load-bearing, not tidiness. The anchor now sits between the
   media container and .user-items-list-carousel__media-inner, whose height is
   an inline padding-bottom percentage set by runtime.js. An inline anchor would
   collapse to a text line box, the percentage would resolve against a different
   containing block, and the strip would lose its height.

   Resting opacity stays at 1 on purpose. Dimming third-party marks by default
   is a common trick but it changes how the band reads at rest, and the section
   was signed off looking the way it looks. The hover is a small dim instead:
   enough to say the logo is live, nothing that draws the eye on its own. */
[data-section-id="681f72a3b02c203237dabec7"] .ea-press-link{
  display:block;cursor:pointer;text-decoration:none;
  transition:opacity .25s ease}
[data-section-id="681f72a3b02c203237dabec7"] .ea-press-link:hover{opacity:.72}

/* These logos carry no text and no underline, so a focus ring is the only
   thing that can show a keyboard user where they are. Offset clears the mark
   itself rather than cropping it. Ink rather than the browser default because
   the band is themed white-bold and the default blue is the one colour in the
   palette that is not ours. Kept at full opacity so a focused logo never reads
   as the hovered, dimmed state. */
[data-section-id="681f72a3b02c203237dabec7"] .ea-press-link:focus-visible{
  outline:2px solid var(--eabc-ink,#2e2e2f);outline-offset:6px;
  border-radius:2px;opacity:1}

@media (prefers-reduced-motion:reduce){
  [data-section-id="681f72a3b02c203237dabec7"] .ea-press-link{transition:none}
}


/* ===========================================================================
   Desktop nav folders: open on keyboard focus, not hover alone.

   The three folder parents (Luxury Portfolio, Neighborhoods, Calculators) are
   now real links to their hub pages, so a keyboard user can reach the hub with
   Enter. Their children were still unreachable: the stylesheet keeps
   .header-nav-folder-content at display:none until :hover, and a display:none
   subtree takes no focus, so Tab jumped straight from the folder title to the
   next top-level item and the five neighborhood links could not be reached at
   all without a mouse.

   Squarespace's own rule for this is
   button.header-nav-folder-title[aria-expanded='true'] + .header-nav-folder-content,
   which needs the header JS we do not ship to flip the attribute. :focus-within
   on the item gets the same result from CSS alone: focusing the parent reveals
   the panel, Tab then walks into it, and focus leaving the item hides it again.
   Specificity is one class above the display:none rule, so no !important.
   =========================================================================== */
.header-nav .header-nav-item--folder:focus-within .header-nav-folder-content{
  display:block;pointer-events:auto}
