/* ===== FONTS =====
   Self-hosted from R2 rather than fetched from Google. Three reasons, in order
   of how much they cost: a third-party font host is a second DNS lookup, a
   second TLS handshake and a dependency whose downtime is invisible to us; the
   files are served with max-age=31536000, immutable, which Google caps far
   lower; and nothing about a visitor is announced to a third party.

   These are the same subsetted WOFF2 files Google serves - same unicode-range
   splits, so a page still downloads only the latin range it needs - copied to
   c21-branding/fonts/ and served from our own domain. Regenerate them with the
   manifest rather than editing by hand: the file names encode style, weight
   and subset, and a mismatch here fails silently as a fallback face.
   ================= */
@font-face {
  font-family: 'Allura';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/allura/allura-normal-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Allura';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/allura/allura-normal-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-italic-300-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-italic-300-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-italic-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-italic-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-italic-500-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-italic-500-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-normal-300-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-normal-300-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-normal-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-normal-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-normal-500-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/cormorant-garamond/cormorant-garamond-normal-500-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/jost/jost-normal-300-700-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(https://library.c21masters.com/c21-branding/fonts/jost/jost-normal-300-700-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* =====================================================================
   CLASSIC DARK — Century 21 Masters agent template
   Mirror of https://library.c21masters.com/global-css/classic-dark.css
   --------------------------------------------------------------------
   espresso ground, Cormorant Garamond over Jost.

   Derived from "Classic Luxury Dark". One design in three themes: classic-light,
   classic-clean and classic-dark share partials/classic/ and
   global-js/classic.js, and differ only in this file.

   Dropped from the source, because nothing renders them any more:
   STATS  (agent highlight), FOOTER. The .svc rules went with the services page.
   Fonts are loaded by head-meta.njk, not here.

   One deliberate divergence from the other two themes: the shared partials'
   paper band, .section-ivory, is inert here and the theme is dark end to end.
   See the rule for why, and read that before adding any light surface.
   ===================================================================== */

/* ---- Design tokens ------------------------------------------------- */
:root {
  /* surfaces */
  --obsidian:   #0B0A08;
  --ink:        #14120E;   /* primary dark surface (warm espresso-black) */
  --ink-2:      #1B1813;   /* raised dark surface */
  --ink-3:      #221E18;
  /* Foreground only on this theme - body text, the burger bars, the corner
     marks. It is not a surface here and nothing should paint a background with
     it. Its raised partner --ivory-2 is gone with the paper band it hovered. */
  --ivory:      #F4F0E7;

  /* accent + text */
  --champagne:      #C7A763;
  --champagne-soft: #DCC495;
  --stone:          #A39B8C;   /* muted text on dark */
  --stone-dim:      #756D60;   /* faint text on dark */

  /* The two paper tokens, aliased to their dark-surface equivalents rather
     than carrying their own values. This theme has no paper left to put them
     on (see .section-ivory below), so a literal --brass or --stone-dark can
     only ever land on espresso.

     Aliasing rather than deleting is what reaches the shared partials.
     partials/classic/ is one set of files for all three themes and it
     hard-codes style="color:var(--brass)" on four links - and only two of
     those are inside the ivory band. The other two (home.njk "Open the full
     search", search.njk) sit on the page's own dark surface and were painting
     the deeper paper gold onto espresso already, band or no band. An inline
     style cannot be overridden from a stylesheet without !important, but the
     custom property it reads can be, so the token is the correct lever.

     Keep both defined even though no rule in this file names --stone-dark any
     more. A var() with no definition and no fallback invalidates the whole
     declaration it sits in, silently - classic-clean has that bug today, where
     it names --brass without defining it and its .qa-note loses its border.
     A shared partial reaching for the token it expects to exist should get a
     colour, not a dropped declaration.

     Restore literal values here only together with a light band to put them
     on. */
  --brass:          var(--champagne);
  --stone-dark:     var(--stone);

  /* lines */
  --line-gold:  rgba(199,167,99,0.30);
  --line-light: rgba(244,240,231,0.12);
  --line-dark:  rgba(20,18,14,0.16);

  /* type */
  --display: "Cormorant Garamond", Georgia, serif;
  --sans: "Jost", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  /* fluid scale */
  /* Was clamp(3.2rem, 1.4rem + 7.6vw, 9.5rem): 132px at 1440 and 152px at the
     ceiling, which took the headline to four and five lines and left the
     paragraph under the fold. 87px at 1440, 100px at the ceiling. */
  --fs-hero:    clamp(2.5rem, 1.3rem + 4.6vw, 6.25rem);
  --fs-display: clamp(2.6rem, 1.4rem + 4.6vw, 6rem);
  --fs-h2:      clamp(2rem, 1.3rem + 2.6vw, 3.6rem);
  --fs-h3:      clamp(1.5rem, 1.1rem + 1.4vw, 2.2rem);
  --fs-lead:    clamp(1.05rem, 0.95rem + 0.5vw, 1.3rem);
  --fs-body:    clamp(1rem, 0.96rem + 0.2vw, 1.08rem);
  --fs-label:   0.72rem;

  /* layout */
  --rail: 56px;                  /* width of the architectural margin rail */
  --pad-x: clamp(1.4rem, 5vw, 7rem);
  --maxw: 1320px;
  --nav-h: 88px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-slow: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ---- Reset --------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--nav-h);
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--sans);
  font-size: var(--fs-body);
  font-weight: 300;
  line-height: 1.7;
  color: var(--ivory);
  background: var(--ink);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; cursor: pointer; background: none; border: none; }
ul { list-style: none; }

::selection { background: var(--champagne); color: var(--ink); }

:focus-visible {
  outline: 2px solid var(--champagne);
  outline-offset: 4px;
}
/* An iframe takes focus as an element but never matched the rule above, so the
   map on the contact page was a stop with no visible indicator. */
iframe:focus {
  outline: 2px solid var(--champagne);
  outline-offset: 2px;
}

/* ---- Typography helpers ------------------------------------------- */
.display { font-family: var(--display); font-weight: 300; line-height: 1; letter-spacing: -0.01em; }
.display em { font-style: italic; font-weight: 400; }

.eyebrow {
  font-family: var(--sans);
  font-size: var(--fs-label);
  font-weight: 400;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: var(--champagne);
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
}
.eyebrow.is-centered { justify-content: center; }

.lead {
  font-size: var(--fs-lead);
  color: var(--stone);
  font-weight: 300;
  max-width: 46ch;
}

/* ---- Layout primitives -------------------------------------------- */
.shell { padding-left: var(--rail); }       /* leaves room for the margin rail */
.wrap  { width: 100%; max-width: var(--maxw); margin: 0 auto; padding-inline: var(--pad-x); }

.block { padding-block: clamp(5rem, 10vw, 9.5rem); }
.block--tight { padding-block: clamp(3.5rem, 7vw, 6rem); }

/* ---- There is no light interlude on this theme ----------------------
   .section-ivory is the shared partials' name for a paper band, and on
   classic-light and classic-clean it is the design. Here it was four slabs of
   #F4F0E7 dropped into an espresso site: communities on Home, "what you can
   expect" on About, and the features band on Buyers and Sellers. The Buyers
   and Sellers pair had already been grounded in the page surface; the other
   two had not, so the same class rendered two different ways depending on the
   page - which is the inconsistency, not the interlude.

   So the class is neutralised on this theme: it paints the page's own surface
   and the page's own text colour. It stays in the file rather than being
   deleted, because the partials still carry the class name and the next reader
   needs to find the reason here instead of restoring the band.

   It resolves to --ink, not --ink-2, and that is a decision: the About band
   holds .guide__col cards that are --ink-2, and the identical .guide block
   renders on Home with no band at all. Ink here makes the two pages match;
   ink-2 would swallow the cards on one of them.

   Both declarations are load-bearing. Setting only the background leaves
   color: var(--ink) inheriting near-black text onto a near-black band. */
.section-ivory { background: var(--ink); color: var(--ivory); }

/* ---- Architectural margin rail (signature) ------------------------ */
.rail {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: var(--rail);
  z-index: 80;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding-block: 1.6rem;
  border-right: 1px solid var(--line-light);
  mix-blend-mode: difference;       /* keeps it legible over any section */
  pointer-events: none;
}
.rail__mark {
  font-family: var(--display);
  font-size: 1.5rem;
  letter-spacing: 0.05em;
  color: #fff;
  pointer-events: auto;
}
.rail__meta {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 0.62rem;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: #fff;
  opacity: 0.8;
}
.rail__line {
  flex: 1;
  width: 1px;
  background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.5), transparent);
  margin-block: 1.4rem;
}

/* ---- Navigation ---------------------------------------------------- */
.nav {
  position: fixed;
  top: 0; left: var(--rail); right: 0;
  height: var(--nav-h);
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-inline: var(--pad-x);
  transition: background 0.5s var(--ease), height 0.5s var(--ease),
              border-color 0.5s var(--ease), backdrop-filter 0.5s var(--ease);
  border-bottom: 1px solid transparent;
}
.nav.is-stuck {
  height: 68px;
  background: rgba(11,10,8,0.72);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--line-light);
}
.brand { display: flex; align-items: baseline; gap: 0.6rem; }
.brand__word {
  font-family: var(--display);
  font-size: 1.7rem;
  letter-spacing: 0.12em;
  line-height: 1;
}
.brand__tag {
  font-size: 0.56rem;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--stone);
}

/* ---- Brand logo lockup (CENTURY 21® Masters) --------------------- */
.logo {
  --ls: 1rem;
  display: inline-flex; flex-direction: column; align-items: center;
  line-height: 1; color: var(--champagne);
}
.logo__word {
  font-family: var(--sans); font-weight: 400;
  font-size: var(--ls); letter-spacing: 0.1em; text-transform: uppercase;
  white-space: nowrap;
}
.logo__masters { font-weight: 600; }
.logo__sub {
  font-family: "Allura", cursive; font-weight: 400;
  font-size: calc(var(--ls) * 2.05); line-height: 0.62;
  letter-spacing: 0; text-transform: none;
  margin-top: calc(var(--ls) * 0.16); color: var(--champagne);
}
.logo--nav { --ls: 0.74rem; }
.nav__cta { padding: 0.85rem 1.4rem; }
.logo--footer { display: flex; width: max-content; --ls: clamp(1.2rem, 2.6vw, 1.8rem); margin-bottom: 0.2rem; }
.logo--pre { --ls: clamp(1.3rem, 4.5vw, 2.4rem); }

.nav__menu { display: flex; align-items: center; gap: clamp(1rem, 1.9vw, 2.2rem); }
.nav__link {
  position: relative;
  font-size: 0.74rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--stone);
  padding-block: 0.4rem;
  transition: color 0.4s var(--ease);
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--champagne);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.5s var(--ease);
}
.nav__link:hover,
.nav__link[aria-current="page"] { color: var(--ivory); }
.nav__link:hover::after,
.nav__link[aria-current="page"]::after { transform: scaleX(1); }

.nav__cta { display: inline-flex; }
.nav__toggle {
  display: none;
  /* 44px is the touch target, not the drawn size: the bars stay 26px wide and
     6px apart, and the extra is padding around them. The other Gold templates
     already sit at 42-44, so this is the set agreeing rather than this one
     growing. */
  width: 44px; height: 44px;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  align-items: flex-end;
}
.nav__toggle span {
  display: block; height: 1px; width: 26px;
  background: var(--ivory);
  transition: transform 0.4s var(--ease), opacity 0.3s var(--ease), width 0.4s var(--ease);
}

/* ---- Buttons ------------------------------------------------------- */
.btn {
  --c: var(--ivory);
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  font-size: 0.74rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--c);
  padding: 1rem 1.9rem;
  border: 1px solid var(--line-gold);
  overflow: hidden;
  isolation: isolate;
  transition: color 0.5s var(--ease), border-color 0.5s var(--ease);
}
.btn::before {
  content: "";
  position: absolute; inset: 0;
  background: var(--champagne);
  transform: translateY(101%);
  transition: transform 0.55s var(--ease);
  z-index: -1;
}
.btn:hover { color: var(--ink); border-color: var(--champagne); }
.btn:hover::before { transform: translateY(0); }
.btn .btn__icon { width: 15px; height: 15px; transition: transform 0.5s var(--ease); }
.btn:hover .btn__icon { transform: translate(3px, -3px); }

.btn--solid { color: var(--ink); border-color: var(--champagne); }
.btn--solid::before { transform: translateY(0); }
.btn--solid:hover::before { transform: translateY(-101%); }
.btn--solid:hover { color: var(--champagne); }

.btn--ghost { color: var(--ink); border-color: var(--line-dark); }
.btn--ghost::before { background: var(--ink); }
.btn--ghost:hover { color: var(--ivory); border-color: var(--ink); }

/* text link with sliding underline */
.tlink {
  display: inline-flex; align-items: center; gap: 0.55rem;
  font-size: 0.74rem; letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--champagne);
  padding-bottom: 4px;
  position: relative;
}
.tlink::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 100%; height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.5s var(--ease);
}
.tlink:hover::after { transform: scaleX(1); }
.tlink svg { width: 14px; height: 14px; transition: transform 0.5s var(--ease); }
.tlink:hover svg { transform: translateX(4px); }

/* =====================================================================
   HERO
   ===================================================================== */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  /* The copy sits on the centre of the photograph rather than on its floor.
     min-height rather than height is what makes that safe: a headline long
     enough to fill the frame grows the section instead of being centred out
     of the top of it and clipped by the overflow rule below. */
  align-items: center;
  overflow: hidden;

  /* The band at the foot of the hero that belongs to the scroll indicator.
     The indicator is taken out of flow so it can centre on the section (see
     .hero__scroll), and .hero__inner reserves the same band as bottom
     padding - which is what keeps the centred copy off it without either box
     knowing the other's height. The line is a variable for the same reason:
     .hero__scroll i draws it, and the reservation must not be able to drift
     from the thing it is reserving for. */
  --hero-scroll-line: 46px;
  --hero-scroll-gap: clamp(1.25rem, 3.5vh, 2.5rem);
  --hero-scroll-band: calc(var(--hero-scroll-line) + var(--hero-scroll-gap));
}
.hero__media { position: absolute; inset: 0; z-index: -2; overflow: hidden; }
.hero__media img {
  width: 100%; height: 116%;
  object-fit: cover;
  object-position: center;
  will-change: transform;
}
.hero__media::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(to top, rgba(11,10,8,0.93) 0%, rgba(11,10,8,0.80) 30%, rgba(11,10,8,0.26) 62%, rgba(11,10,8,0.45) 100%);
  z-index: 1;
}
.hero__inner {
  width: 100%;
  /* .hero centres this box, so these two paddings are what the centring is
     measured against: they hold the copy clear of the fixed bar above it and
     of the scroll indicator below it, and they come out within a few pixels
     of each other, which is what puts the copy on the centre line rather
     than a little under it.

     The 2rem above the bar goes fluid on a short viewport. At 480px tall the
     fixed value spent 118px of 480 on padding before the eyebrow, which put
     the last line of the paragraph 5px under the fold on classic-clean. 3vh
     reaches the 2rem cap at 667px tall, so nothing changes on a normal phone
     or above - only the short end gets the room back. */
  padding-top: calc(var(--nav-h) + clamp(0.75rem, 3vh, 2rem));
  padding-bottom: calc(var(--hero-scroll-band) + clamp(0.75rem, 3vh, 2rem));
}
.hero__title {
  font-size: var(--fs-hero);
  /* Out from 16ch with the size coming down. Holding the old measure would
     have made the column narrower in pixels and added lines rather than
     removing them; 20ch is where this title breaks in two. */
  max-width: 20ch;
  /* On .hero__title, not .display - other headings share that class. 1 was
     drawn for a single line at display size; at 87px over two or three it
     sets the lines touching. */
  line-height: 1.06;
  margin-block: 1.6rem 2.2rem;
  /* The headline is agent copy, so its longest word is not known at design
     time. A word with no break opportunity has to break rather than run out
     of the hero, which clips it. Same guard as timeless and aurelia. */
  overflow-wrap: break-word;
}
/* Paragraph, then button, down the same left edge. The two were a
   space-between row, which put the button at the far right of the hero on its
   own: it read as a third element rather than as the paragraph's action, and
   it left the empty shelf under the copy that the QA screenshot marks.

   align-items is flex-start rather than the column default - stretch would
   size the button to the width of the hero. The gap is .hero__title's bottom
   margin, so eyebrow, headline, paragraph and button keep one rhythm. The
   phone-width .btn rule still takes the button full width, as it does for
   every standalone CTA on the site. */
.hero__foot {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2.2rem;
}
/* The paragraph sits on the photograph, so it cannot keep .lead's page
   treatment. #A39B8C at weight 300 composites to about 2.9:1 over a bright
   frame; dimmed ivory holds ~6:1 against the same frame and still reads a
   step below the headline, which is what the muted grey was for. The scrim
   is left alone - the text was the thing that was wrong, and darkening the
   photograph further would cost the hero its light. */
.hero__sub {
  max-width: 40ch;
  color: rgba(244, 240, 231, 0.86);
  font-weight: 400;
  line-height: 1.65;
}
/* Bottom centre of the hero, and out of flow to get there.

   In flow it was the second item of .hero's flex row: it sat at the bottom
   right beside the copy, and it took its width out of the copy's measure -
   flex:none and width:auto were there to limit that, and the phone-width rule
   in the responsive block stacked the row to undo it. Positioning it removes
   the cause, so all three of those are gone with it.

   .hero__inner reserves --hero-scroll-band under the copy, which is what
   keeps the two apart at every width - do not put this back in flow without
   taking that reservation out. */
.hero__scroll {
  position: absolute;
  left: 0; right: 0;
  bottom: var(--hero-scroll-gap);
  /* .wrap caps this box at --maxw and centres it with auto margins, which is
     under-defined for an absolutely positioned box spanning left to right and
     is resolved differently by different engines. So the cap comes off and
     the label is centred by justify-content instead; .wrap's padding-inline
     still keeps it off the edge of a phone. */
  max-width: none;
  display: flex; align-items: center; justify-content: center; gap: 0.8rem;
  font-size: 0.62rem; letter-spacing: 0.3em; text-transform: uppercase;
  color: var(--stone);
}
.hero__scroll i {
  display: block; width: 1px; height: var(--hero-scroll-line);
  background: linear-gradient(var(--champagne), transparent);
  animation: drop 2.4s var(--ease) infinite;
}
@keyframes drop {
  0% { transform: scaleY(0); transform-origin: top; }
  40% { transform: scaleY(1); transform-origin: top; }
  60% { transform: scaleY(1); transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}

/* page header (interior pages, no full-bleed hero) */
.phead { position: relative; padding-top: calc(var(--nav-h) + clamp(3rem, 9vw, 7rem)); }
.phead__index { display: none; }
.phead__title { font-size: var(--fs-display); max-width: 18ch; position: relative; z-index: 1; }

/* =====================================================================
   INTRO SPLIT
   ===================================================================== */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2.5rem, 6vw, 7rem);
  align-items: center;
}
.split--portrait { grid-template-columns: 0.85fr 1fr; }
.split__media { position: relative; overflow: hidden; }
.split__media img { width: 100%; aspect-ratio: 4/5; object-fit: cover; transition: transform 1.4s var(--ease-slow); }
.split__media:hover img { transform: scale(1.04); }
.split__media--tall img { aspect-ratio: 3/4; }
.split__title { font-size: var(--fs-h2); margin-block: 1.4rem 1.6rem; max-width: 18ch; }
.split__body p + p { margin-top: 1.2rem; }
.split__body { color: var(--stone); }
.split__cta { margin-top: 2.4rem; }

/* signature corner mark on media */
.framed { position: relative; }
.framed::before, .framed::after {
  content: ""; position: absolute; width: 26px; height: 26px; z-index: 2;
  border-color: var(--champagne); border-style: solid; border-width: 0;
}
.framed::before { top: 18px; left: 18px; border-top-width: 1px; border-left-width: 1px; }
.framed::after  { bottom: 18px; right: 18px; border-bottom-width: 1px; border-right-width: 1px; }

/* =====================================================================
   FEATURED COLLECTION  (asymmetric editorial)
   ===================================================================== */
.collection-head {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 1.5rem;
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}
.collection-head h2 { font-size: var(--fs-h2); max-width: 14ch; margin-top: 1.2rem; }

.estates { display: grid; gap: clamp(3rem, 6vw, 6rem); }
.estate {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.6rem, 4vw, 4rem);
  align-items: center;
}
.estate:nth-child(even) .estate__media { order: 2; }
.estate__media { position: relative; overflow: hidden; }
.estate__media img {
  width: 100%; aspect-ratio: 16/11; object-fit: cover;
  transition: transform 1.5s var(--ease-slow), filter 1.5s var(--ease-slow);
}
.estate:hover .estate__media img { transform: scale(1.05); }
.estate__no {
  position: absolute; top: 1.2rem; left: 1.2rem; z-index: 2;
  font-family: var(--display); font-size: 1.4rem; color: var(--ivory);
  mix-blend-mode: difference;
}
.estate__loc { font-size: 0.72rem; letter-spacing: 0.28em; text-transform: uppercase; color: var(--champagne); }
.estate__name { font-family: var(--display); font-size: var(--fs-h3); line-height: 1.05; margin-block: 0.9rem 1.3rem; }
.estate__desc { color: var(--stone); max-width: 42ch; }
.estate__spec {
  display: flex; flex-wrap: wrap; gap: 1.8rem;
  margin-block: 1.8rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--line-light);
}
.estate__spec li { display: flex; align-items: center; gap: 0.6rem; font-size: 0.82rem; color: var(--stone); letter-spacing: 0.04em; }
.estate__spec svg { width: 17px; height: 17px; color: var(--champagne); stroke-width: 1.4; }
.estate__foot { display: flex; align-items: baseline; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; }
.estate__price { font-family: var(--display); font-size: 1.6rem; color: var(--ivory); }

/* =====================================================================
   CTA banner
   ===================================================================== */
.cta-banner { text-align: center; position: relative; overflow: hidden; }
.cta-banner__big { font-size: var(--fs-display); max-width: 20ch; margin: 1.6rem auto 2.6rem; }
.cta-banner .lead { margin-inline: auto; margin-bottom: 0; }

/* =====================================================================
   TESTIMONIALS
   ===================================================================== */
.quotes { display: grid; gap: clamp(2rem, 4vw, 3rem); }
.quotes--row { grid-template-columns: repeat(3, 1fr); }
.quote {
  padding: clamp(2rem, 3vw, 2.8rem);
  border: 1px solid var(--line-light);
  display: flex; flex-direction: column; gap: 1.6rem;
  transition: border-color 0.6s var(--ease), transform 0.6s var(--ease);
}
.quote:hover { border-color: var(--line-gold); transform: translateY(-4px); }
.quote__mark { font-family: var(--display); font-size: 3.4rem; line-height: 0.4; color: var(--champagne); height: 1.4rem; }
.quote__text { font-family: var(--display); font-size: 1.35rem; line-height: 1.45; font-weight: 300; }
.quote__by { margin-top: auto; font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--stone); }

/* =====================================================================
   SERVICES
   ===================================================================== */
.services-list { border-top: 1px solid var(--line-gold); }
.service {
  position: relative;
  display: grid;
  grid-template-columns: clamp(3rem, 6vw, 6.5rem) 1fr auto;
  gap: clamp(1.6rem, 4vw, 4rem);
  align-items: start;
  padding-block: clamp(2.6rem, 4.5vw, 4rem);
  border-bottom: 1px solid var(--line-light);
  transition: padding-left 0.6s var(--ease), background 0.6s var(--ease);
}
/* gold accent that draws down the left edge on hover */
.service::after {
  content: ""; position: absolute; left: 0; top: 0; bottom: -1px; width: 1px;
  background: var(--champagne); transform: scaleY(0); transform-origin: top;
  transition: transform 0.6s var(--ease);
}
.service:hover {
  padding-left: clamp(1rem, 2vw, 2rem);
  background: linear-gradient(90deg, rgba(199,167,99,0.05), transparent 55%);
}
.service:hover::after { transform: scaleY(1); }
.service__no {
  font-family: var(--display); font-style: italic;
  font-size: clamp(1.7rem, 2.6vw, 2.4rem); line-height: 1.15;
  color: var(--stone-dim);
  transition: color 0.6s var(--ease);
}
.service:hover .service__no { color: var(--champagne); }
.service__sub { display: block; font-family: var(--sans); font-size: 0.66rem; letter-spacing: 0.28em; text-transform: uppercase; color: var(--champagne); margin-bottom: 0.8rem; }
.service__name { font-family: var(--display); font-size: var(--fs-h3); line-height: 1.04; max-width: 16ch; }
.service__desc { color: var(--stone); max-width: 58ch; margin-top: 1.2rem; }
.service__link {
  align-self: center; justify-self: end; flex: none;
  width: 54px; height: 54px; display: grid; place-items: center;
  border: 1px solid var(--line-gold); border-radius: 50%;
  color: var(--champagne);
  transition: background 0.55s var(--ease), color 0.55s var(--ease), transform 0.55s var(--ease);
}
.service:hover .service__link { background: var(--champagne); color: var(--ink); transform: translate(4px, -4px); }
.service__link svg { width: 19px; height: 19px; stroke-width: 1.4; }

/* feature cards (services secondary) */
/* Two columns, not three. Both pages that render this grid — buyers and
   sellers — carry exactly four cards, so a three-column row left the fourth
   alone with a two-cell hole beside it, and the grid's own background showed
   through as a grey slab. 2x2 holds at every width down to the single-column
   breakpoint.

   The grid paints the hairlines between cards through its own background, so
   both it and its border take the paper-on-ink line rather than the
   ink-on-paper one - otherwise the card seams vanish into the dark surface. */
.feature-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--line-light); border: 1px solid var(--line-light); }
.feature {
  background: var(--ink-2);
  padding: clamp(2rem, 3vw, 2.8rem);
  display: flex; flex-direction: column; gap: 1rem;
  transition: background 0.5s var(--ease);
}
.feature:hover { background: var(--ink-3); }
.feature__icon svg { width: 26px; height: 26px; color: var(--champagne); stroke-width: 1.2; }
.feature h4 { font-family: var(--display); font-size: 1.45rem; font-weight: 400; }
.feature p { color: var(--stone); font-size: 0.96rem; }

/* =====================================================================
   TIMELINE
   ===================================================================== */
/* No .section-ivory variants below. The band is the page surface on this theme,
   so a timeline inside one is styled by the base rules; a paper override here
   would put ink-on-paper hairlines and the darker gold onto espresso the day
   someone moved the Buyers timeline into that band. */
.timeline { border-top: 1px solid var(--line-gold); }
.tl-item {
  --tl-dot: 11px;
  display: grid;
  grid-template-columns: clamp(4rem, 6vw, 5.5rem) 30px minmax(0, 1fr);
  column-gap: clamp(1.4rem, 2.6vw, 2.4rem);
  align-items: stretch;
  padding-block: clamp(1.7rem, 2.8vw, 2.4rem);
  border-bottom: 1px solid var(--line-light);
}
.tl-year {
  font-family: var(--display); font-style: italic;
  font-size: clamp(1.5rem, 2.2vw, 2rem); line-height: 1.15;
  color: var(--champagne); padding-top: 1px;
}
.tl-node { position: relative; }
.tl-node::before {
  content: ""; position: absolute; z-index: 1; top: 7px; left: 50%;
  transform: translateX(-50%);
  width: var(--tl-dot); height: var(--tl-dot); border-radius: 50%;
  background: var(--champagne); box-shadow: 0 0 0 4px rgba(199,167,99,0.14);
  transition: transform 0.5s var(--ease), box-shadow 0.5s var(--ease);
}
.tl-node::after {
  content: ""; position: absolute; left: 50%; transform: translateX(-50%);
  top: 0; bottom: 0; width: 1px; background: var(--line-gold);
}
.tl-item:first-child .tl-node::after { top: calc(7px + var(--tl-dot) / 2); }
.tl-item:last-child .tl-node::after { bottom: auto; height: calc(7px + var(--tl-dot) / 2); }
.tl-item:hover .tl-node::before { transform: translateX(-50%) scale(1.3); box-shadow: 0 0 0 6px rgba(199,167,99,0.12); }
.tl-title { font-family: var(--display); font-size: clamp(1.35rem, 1.8vw, 1.65rem); line-height: 1.12; margin-bottom: 0.55rem; }
.tl-body { color: var(--stone); max-width: 60ch; line-height: 1.65; }

/* affiliations marquee-ish row */
.affil { display: flex; flex-wrap: wrap; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
.affil span {
  font-family: var(--display); font-size: clamp(1.2rem, 2.4vw, 1.9rem);
  color: var(--stone-dim); letter-spacing: 0.02em;
  transition: color 0.5s var(--ease);
}
.affil span:hover { color: var(--champagne); }

/* =====================================================================
   CONTACT
   ===================================================================== */
.contact-grid { display: grid; grid-template-columns: 1.2fr 0.8fr; gap: clamp(2.5rem, 6vw, 6rem); }
.field { position: relative; margin-bottom: 2.4rem; }
.field input, .field textarea {
  width: 100%;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line-light);
  color: var(--ivory);
  font-family: var(--sans); font-weight: 300; font-size: 1.05rem;
  padding: 0.7rem 0;
  transition: border-color 0.5s var(--ease);
}
.field textarea { resize: vertical; min-height: 120px; }
.field label {
  position: absolute; left: 0; top: 0.7rem;
  font-size: 0.78rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--stone-dim);
  pointer-events: none;
  transition: transform 0.45s var(--ease), color 0.45s var(--ease), font-size 0.45s var(--ease);
}
.field input:focus, .field textarea:focus { outline: none; border-color: var(--champagne); }
.field input:focus + label,
.field textarea:focus + label,
.field input:not(:placeholder-shown) + label,
.field textarea:not(:placeholder-shown) + label {
  transform: translateY(-2rem);
  font-size: 0.62rem;
  color: var(--champagne);
}
.field input::placeholder, .field textarea::placeholder { color: transparent; }

.form-note { font-size: 0.78rem; color: var(--stone-dim); margin-top: -0.8rem; margin-bottom: 1.8rem; }
.form-status {
  margin-top: 1.4rem; font-size: 0.8rem; letter-spacing: 0.12em;
  color: var(--champagne); opacity: 0; transform: translateY(6px);
  transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
}
.form-status.is-shown { opacity: 1; transform: translateY(0); }

.contact-detail { display: flex; flex-direction: column; gap: 2.2rem; }
.cd-item { display: flex; flex-direction: column; gap: 0.4rem; }
.cd-item .label { font-size: 0.66rem; letter-spacing: 0.26em; text-transform: uppercase; color: var(--champagne); }
.cd-item a, .cd-item p { font-family: var(--display); font-size: 1.4rem; }
.cd-item small { color: var(--stone); }

.map-frame {
  position: relative; overflow: hidden;
  border: 1px solid var(--line-light);
  margin-top: clamp(3rem, 6vw, 5rem);
}
.map-frame iframe {
  width: 100%; height: clamp(300px, 42vw, 460px);
  border: 0; display: block;
  filter: grayscale(1) contrast(1.05) brightness(0.62) sepia(0.34) hue-rotate(2deg);
  transition: filter 0.8s var(--ease);
}
.map-frame:hover iframe { filter: grayscale(0.6) contrast(1.05) brightness(0.8) sepia(0.1); }
.map-frame__tag {
  position: absolute; left: 1.4rem; bottom: 1.4rem; z-index: 2;
  background: var(--ink); border: 1px solid var(--line-gold);
  padding: 0.7rem 1.2rem; font-size: 0.64rem; letter-spacing: 0.24em; text-transform: uppercase; color: var(--champagne);
  pointer-events: none;
}

/* =====================================================================
   BUYER / SELLER GUIDE — two columns
   ===================================================================== */
.guide { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.4rem, 3vw, 2.2rem); }
.guide__col {
  display: flex; flex-direction: column;
  padding: clamp(2rem, 4vw, 3.2rem);
  border: 1px solid var(--line-light); border-radius: 3px;
  background: var(--ink-2);
  /* Names its own colour rather than inheriting one. This began as a fix for
     these cards sitting inside .section-ivory: the band set color: var(--ink),
     so anything on the card that did not state a colour inherited near-black
     onto a near-black surface, and .guide__title read at 1.05:1. The band is
     the page surface now, so the inheritance is already correct - but the
     declaration stays, because it is what makes the card independent of
     whatever the section around it decides to be. 15.5:1. */
  color: var(--ivory);
  transition: border-color 0.6s var(--ease), transform 0.6s var(--ease), background 0.6s var(--ease);
}
.guide__col:hover { border-color: var(--line-gold); transform: translateY(-6px); background: var(--ink-3); }
.guide__no { font-size: 0.7rem; letter-spacing: 0.26em; text-transform: uppercase; color: var(--champagne); }
.guide__title { font-family: var(--display); font-size: var(--fs-h3); margin-top: 0.7rem; }
.guide__lead { color: var(--stone); margin-top: 1rem; max-width: 38ch; }
.guide__list {
  counter-reset: g; margin-top: 1.8rem; padding-top: 1.8rem;
  border-top: 1px solid var(--line-light);
  display: flex; flex-direction: column; gap: 1.1rem;
}
.guide__list li { display: flex; gap: 1rem; align-items: baseline; color: var(--ivory); font-size: 0.98rem; line-height: 1.5; }
.guide__list li::before {
  counter-increment: g; content: counter(g, decimal-leading-zero);
  font-family: var(--display); font-size: 1rem; color: var(--champagne);
  min-width: 1.8em; flex: none;
}
.guide__cta { margin-top: auto; padding-top: 2.2rem; }

/* =====================================================================
   LISTINGS SYNDICATED TO — partner logo tiles
   --------------------------------------------------------------------
   The real SVGs from c21-branding/syndicated-logos/ in R2, each on its own
   white square tile, monochrome until pointed at: five tiles per row on a
   desktop, four on a tablet, two on a phone, and a short last row centres
   itself. Not a marquee - nothing here scrolls or animates on its own.

   Four things here are not free to change:

   - The tile is white because that is what makes the logos correct, not
     because it is a card. Five of the ten files are raster images inside an
     SVG wrapper, and three of those (Robb Report, Mansion Global, duPont
     Registry) sit on an opaque #FFF plate. The logo multiplies onto the
     tile, and multiply leaves white exactly as it finds it: on a white tile
     the plate vanishes and every brand colour renders true. Any other tile
     colour brings the plates back as pale boxes.

   - isolation on the tile is what that blend needs. mix-blend-mode reaches
     the backdrop of its nearest stacking context, so without it the logo
     blends with whatever is painted below the list - the page canvas, and
     the .reveal fade mid-animation, which is where the plates used to
     flash. Isolating makes the tile's own white the entire backdrop, so
     nothing underneath it matters any more. It is also why this list no
     longer repaints the body background the way it had to before.

   - The rest state may darken and desaturate but must never darken white.
     grayscale plus a little contrast is the whole of it, and each mark
     lands on its own luminance: eight of the ten fall between #000 and
     #6C6C6C, so the wall reads as dark grey. A brightness step would take
     them lower and take the white with them - both the plates and the
     white inside realtor.com's house and the ListHub wordmark - because to
     a filter white and ink are the same channel.

   - The two size limits work together and both are relative to the tile, so
     a tile of any width shows the same composition. max-width keeps a wide
     wordmark inside the tile. max-height is the optical cap height
     (--syn-cap, a share of the tile inner height) divided by that file's ink
     fraction (--syn-fill, set per item in the partial), which is what puts
     every mark on the same optical size - cap them all to one box instead and
     Properstar, duPont Registry and Mansion Global read at half the size of
     their neighbours. Re-measure --syn-fill when a file is replaced; the
     number belongs to the file, not to the partner.

     Equal ink boxes only mean equal cap height while a mark is one line of
     type. A lockup that stacks an icon over its wordmark spends that same box
     on two rows and the gap between them, so its wordmark comes out around
     half the size of its neighbours - CREtech, measured, was 23% of the tile
     wide against a 38-71% band. Those files carry --syn-lift, a multiplier on
     the cap. Unlike fill it is a judgement rather than a measurement, so the
     partial records how each one was arrived at.

     The widest marks (realtor.com, JamesEdition, Properstar) end up limited
     by width rather than by cap height, which is what a square tile does to a
     7:1 wordmark and is preferable to letting it run out of the tile.
   ===================================================================== */
.trust-section { text-align: center; }
.trust {
  --syn-gap: clamp(0.75rem, 1.5vw, 1.1rem);
  /* The optical cap height every mark is normalised to, as a share of the
     tile's inner height rather than of the viewport - so the composition
     inside a tile is the same on a phone as it is on a desktop. */
  --syn-cap: 19%;
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--syn-gap);
  max-width: 880px;
  margin: clamp(2rem, 4vw, 3rem) auto 0;
  list-style: none;
}
/* Column count. A basis of (100/n)% less one gap fits exactly n tiles per row
   and can never fit n+1, whatever width the list ends up with, so the count
   holds without measuring anything. These two overrides belong next to the
   rule they change rather than in the responsive block at the end of the
   file: the count is the layout here, not a tweak to it. max-width is a
   ceiling on the tile, not a width: without it a 4-column tablet row makes
   tiles half again as large as the 5-column desktop ones, since each track is
   a share of the row. A cap narrows a tile, so it is the one change here that
   could in principle fit an extra one on a line: at 168px it cannot, at any
   width, for any of the three counts. Re-check that if you raise it. */
.trust__item { flex: 0 0 calc(20% - var(--syn-gap)); max-width: 168px; }
@media (max-width: 880px) { .trust__item { flex-basis: calc(25% - var(--syn-gap)); } }
@media (max-width: 540px) { .trust__item { flex-basis: calc(50% - var(--syn-gap)); } }
.trust__link {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1;
  /* Percentage padding resolves against the tile's own width, so the frame
     around the logo stays the same share of the tile at every breakpoint. */
  padding: 14%;
  /* The light surface this theme otherwise refuses - read the --brass note at
     the top and the .section-ivory rule before taking it as a precedent. What
     that rule rejects is a paper BAND: four slabs of #F4F0E7 that rendered
     two different ways across the pages sharing the class. This is not that.
     It is ten small plates in one section on one page, and it is load-bearing
     rather than decorative: the espresso ground cannot show a white-plated
     logo at all. The theme already conceded the point by fading an ivory card
     in under the pointer here; the only change is that the card no longer
     goes away, which is also what lets one blend mode serve at rest and on
     hover instead of switching between screen and multiply mid-transition.
     Pure white rather than --ivory because the plates in the files are #FFF,
     and multiply only erases them into a tile that matches. */
  background: #fff;
  border: 1px solid var(--line-dark); border-radius: 3px;
  isolation: isolate;
  transition: border-color 0.3s var(--ease), transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.trust__logo {
  display: block;
  width: auto; height: auto;
  max-width: 100%;
  max-height: calc(var(--syn-cap) * var(--syn-lift, 1) / var(--syn-fill, 1));
  filter: grayscale(1) contrast(1.06);
  mix-blend-mode: multiply;
  transition: filter 0.3s var(--ease);
}
/* Brand colour on hover and on keyboard focus, so the reveal is not
   pointer-only. Both filter lists name the same functions in the same order,
   which is what lets the colour ease in rather than snap. The focus ring is
   the global :focus-visible rule: champagne, and it sits 4px outside the tile
   on the espresso ground rather than on the white, which is where it reads.
   Do not tighten --syn-gap below the room it needs. */
.trust__link:hover,
.trust__link:focus-visible {
  border-color: var(--line-gold);
  transform: translateY(-4px);
}
/* The lift shadow is on hover alone, so the keyboard ring keeps whatever the
   global :focus-visible rule paints - box-shadow is one property and a tile
   outranks that rule. */
.trust__link:hover { box-shadow: 0 18px 36px -24px rgba(0,0,0,0.7); }
.trust__link:hover .trust__logo,
.trust__link:focus-visible .trust__logo { filter: grayscale(0) contrast(1); }

/* Agent credential line (About bio) — name, role, and DRE together. */
.agent-id { display: flex; flex-wrap: wrap; align-items: center; gap: 0.7rem 1.1rem; margin-top: 1.5rem; }
.agent-id__name { font-family: var(--display); font-size: 1.55rem; line-height: 1; letter-spacing: 0.02em; color: var(--champagne-soft); }
.agent-id__role { font-size: 0.72rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--stone); }
.agent-id__dre {
  font-size: 0.7rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--champagne);
  border: 1px solid var(--line-gold); border-radius: 2px;
  padding: 0.34rem 0.7rem;
}/* =====================================================================
   SCROLL REVEAL
   ===================================================================== */
.reveal { opacity: 0; transform: translateY(34px); transition: opacity 1s var(--ease), transform 1s var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }
.reveal[data-delay="1"] { transition-delay: 0.1s; }
.reveal[data-delay="2"] { transition-delay: 0.2s; }
.reveal[data-delay="3"] { transition-delay: 0.3s; }
.reveal[data-delay="4"] { transition-delay: 0.4s; }

/* hairline that draws itself in */
.draw { transform: scaleX(0); transform-origin: left; transition: transform 1.1s var(--ease-slow); }
.draw.is-in { transform: scaleX(1); }

/* clip-reveal for media */
.clip { clip-path: inset(0 0 100% 0); transition: clip-path 1.3s var(--ease-slow); }
.clip.is-in { clip-path: inset(0 0 0% 0); }

/* staggered cascade — children of a [data-stagger] container ease in one
   after another once the container scrolls into view */
[data-stagger].reveal { opacity: 1; transform: none; }
[data-stagger] > * {
  opacity: 0; transform: translateY(10px) scale(0.985);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
[data-stagger].is-in > * { opacity: 1; transform: none; }
[data-stagger].is-in > *:nth-child(1) { transition-delay: 0.05s; }
[data-stagger].is-in > *:nth-child(2) { transition-delay: 0.12s; }
[data-stagger].is-in > *:nth-child(3) { transition-delay: 0.19s; }
[data-stagger].is-in > *:nth-child(4) { transition-delay: 0.26s; }
[data-stagger].is-in > *:nth-child(5) { transition-delay: 0.33s; }
[data-stagger].is-in > *:nth-child(6) { transition-delay: 0.40s; }

/* Fail-safe: if JavaScript never runs (disabled, blocked, or a failed
   script load), the scroll-reveal classes can never resolve. Without JS
   we must never hide content, so show everything and skip the preloader. */
html:not(.js) .reveal,
html:not(.js) .draw,
html:not(.js) .clip,
html:not(.js) [data-stagger] > * { opacity: 1 !important; transform: none !important; clip-path: none !important; }
html:not(.js) .preloader { display: none !important; }

/* =====================================================================
   PRELOADER
   ===================================================================== */
.preloader {
  position: fixed; inset: 0; z-index: 200;
  background: var(--ink);
  display: grid; place-items: center;
  transition: opacity 0.8s var(--ease), visibility 0.8s var(--ease);
}
.preloader.is-done { opacity: 0; visibility: hidden; }
.preloader__mark { text-align: center; }
.preloader__mark .w { font-family: var(--display); font-size: clamp(2.5rem, 8vw, 5rem); letter-spacing: 0.18em; overflow: hidden; }
.preloader__mark .w span { display: inline-block; transform: translateY(110%); animation: rise 0.9s var(--ease) forwards; }
.preloader__mark .w span:nth-child(2){ animation-delay: 0.07s; }
.preloader__mark .w span:nth-child(3){ animation-delay: 0.14s; }
.preloader__mark .w span:nth-child(4){ animation-delay: 0.21s; }
@keyframes rise { to { transform: translateY(0); } }
.preloader__mark .logo { animation: logo-in 1s var(--ease) both; }
@keyframes logo-in { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } }
.preloader__line { height: 1px; background: var(--champagne); margin: 1.4rem auto 0; width: 0; animation: grow 1.1s 0.3s var(--ease) forwards; }
@keyframes grow { to { width: 100%; } }

/* =====================================================================
   RESPONSIVE
   ===================================================================== */
/* Burger overlay — the overflow menu, and the phone menu, and the same thing
   at every width in between. This used to be @media (max-width: 1024px), one
   number standing in for 586 different agent-name lengths since the wordmark
   shares this row. global-js/nav-fit.js keeps as many items inline as the row
   can hold and nests the rest in here. */
.nav-panel {
  position: fixed;
  top: 0; left: 0; width: 100%;
  /* Height follows the contents rather than filling the viewport. It holds
     nine items on a phone and sometimes one on a desktop, and a full-screen
     overlay containing a single word reads as a broken page. */
  height: auto;
  max-height: 100svh;
  /* A drawer from the right rather than a full-screen overlay dropping from
     the top. Width is half the window from 442px up and the whole window at
     441 and below; height fills, which it can now do because the panel holds
     either the entire nav or nothing rather than a single leftover link. */
  top: 0; right: 0; left: auto;
  width: 50%;
  height: 100svh;
  /* The top also clears the close button. The bar keeps its X above this drawer
     (z-index 70 against 65), and on a 480px-tall screen the 4rem floor of the
     figure below put the mark level with it - measured, 1px of overlap at
     320x480 and 3px of clearance at 320x568, which is not a margin.
     max() leaves the drawer's own rhythm alone wherever it is already generous
     enough and lifts only the short end, so nothing changes above ~550px tall. */
  padding-top: max(clamp(4rem, 12vh, 8rem), calc(var(--nav-h) + 0.5rem));
  padding-bottom: clamp(4rem, 12vh, 8rem);
  padding-inline: clamp(1.5rem, 4vw, 2.5rem);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 2.2rem;
  background: var(--obsidian);
  transform: translateX(100%);
  opacity: 0;
  /* visibility carries a delay so it flips instantly on open and only once
     the slide has finished on close; without it the panel disappears on the
     first frame of closing and the animation is never seen. */
  transition: transform 0.45s var(--ease),
              opacity 0.45s var(--ease),
              visibility 0s linear 0.45s;
  z-index: 65;
  /* The overlay sits off-screen rather than hidden, so without this its links
     stay in the tab order while it is closed. */
  visibility: hidden;
}
/* No auto margins here, and that is the point.
   The panel used to centre its contents with justify-content, which put the
   overflow at both ends and made the top half unreachable. Auto margins fixed
   the reachability but kept the drift: the mark landed 32px from the panel top
   on a short screen and 180px on a tall one, and on a tall drawer it left a
   168px void between the mark and the first link - the logo read as stranded
   rather than as the head of the menu.
   So the stack is simply top-aligned: the mark sits at the panel's top padding,
   the links follow one gap below it, and both are the same on every screen. It
   costs nothing in emptiness, because the panels that could look sparse
   (classic, california, timeless) are height:auto and shrink to their content;
   the two side drawers are full-height by design, where a menu that starts at
   the top is the ordinary thing. justify-content: flex-start above is what
   keeps the top scrollable when the content is taller than the screen. */
.nav-panel.is-open {
  transform: translateX(0);
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

/* Phones take the whole window: half of 400px is a column of menu beside a
   column of page nobody can read. */
@media (max-width: 441px) {
  .nav-panel { width: 100%; }
}
.nav-panel .nav__menu { flex-direction: column; justify-content: center; gap: 2.2rem; }
.nav-panel .nav__link { font-size: 1rem; }
.nav-panel .btn { margin-top: 1rem; }

/* The burger appears only when the overlay has something in it. nav-fit.js
   sets this to "false" when every item fits inline; it is absent until the
   script runs, and absent has to mean visible - that is the state a phone
   loads in, with every item still in the overlay. */
.nav__toggle { display: flex; z-index: 70; }
[data-nav-overflow="false"] .nav__toggle { display: none; }
.nav.is-nav-open .nav__toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav.is-nav-open .nav__toggle span:nth-child(2) { opacity: 0; width: 0; }
.nav.is-nav-open .nav__toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* An inline nav link that wraps to a second line is the thing overflow is
   there to prevent, so it must not be an option the row can take instead. */
[data-nav-fit-inline] .nav__link, [data-nav-fit-inline] .nav__cta { white-space: nowrap; }

/* ---- Nav submenus --------------------------------------------------- */
/* Buyers carries Calculator; Sellers carries Home Valuation and Sold. A group
   is ONE element, so nav-fit.js moves it whole and knows nothing about the
   nesting - all that is left is how it reads in each of the two places it can
   land.

   Inline it is an absolutely positioned dropdown, and that is not a styling
   preference: a submenu in flow would make the group as wide as its widest
   child, nav-fit would measure that width, and the group would nest at every
   screen size - so the dropdown would never once be seen.

   It opens on :hover and on :focus-within, and no script owns either. Focus
   reaches the parent link, which is always visible, before it can reach into
   the submenu, so :focus-within is already true by the time the next Tab
   lands inside. That is what lets the closed state use visibility:hidden and
   keep the submenu out of the tab order until it is on screen. */
.nav__group { position: relative; display: flex; align-items: center; }
.nav__group > .nav__link { display: inline-flex; align-items: center; gap: 0.5em; }
.nav__sub { display: flex; flex-direction: column; }

/* Drawn from borders rather than an icon: Lucide is inlined in
   global-js/classic.js and runs after first paint, so an <i data-lucide> here
   would be an empty box in the bar until that script landed. */
.nav__caret {
  width: 0.34em; height: 0.34em; flex: none;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: translateY(-0.1em) rotate(45deg);
  transition: transform 0.4s var(--ease);
}

/* Inline: the dropdown. A raised dark surface rather than the bar's own
   translucency - a blurred panel over a blurred bar doubles the blur and the
   labels stop being legible. */
[data-nav-fit-inline] .nav__sub {
  position: absolute;
  top: 100%; left: -1.1rem;
  min-width: max-content;
  margin-top: 0.6rem;
  padding-block: 0.5rem;
  background: var(--ink-2);
  border: 1px solid var(--line-light);
  box-shadow: 0 24px 52px -28px rgba(0,0,0,0.75);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease), visibility 0.35s var(--ease);
  z-index: 75;
}
/* The gap between the label and the card is dead ground the pointer has to
   cross, and crossing it would close the menu. This bridges it. */
[data-nav-fit-inline] .nav__sub::before {
  content: ""; position: absolute; left: 0; right: 0; top: -0.6rem; height: 0.6rem;
}
[data-nav-fit-inline] .nav__group:hover .nav__sub,
[data-nav-fit-inline] .nav__group:focus-within .nav__sub {
  opacity: 1; visibility: visible; transform: translateY(0);
}
[data-nav-fit-inline] .nav__group:hover .nav__caret,
[data-nav-fit-inline] .nav__group:focus-within .nav__caret { transform: translateY(0.08em) rotate(-135deg); }
[data-nav-fit-inline] .nav__sub .nav__link { padding: 0.5rem 1.1rem; }
/* The sliding champagne rule belongs to the bar. Inside a card it reads as a
   border on the wrong edge. */
[data-nav-fit-inline] .nav__sub .nav__link::after { display: none; }
[data-nav-fit-inline] .nav__sub .nav__link:hover { background: var(--ink-3); }

/* Panel: an indented block, always open. There is no disclosure to tap - the
   panel exists to show what did not fit, so hiding half of it behind a second
   interaction would defeat it. The overlay centres its links, so the submenu
   is centred under a hairline rather than indented behind a left border. */
[data-nav-fit-panel] .nav__group { flex-direction: column; align-items: center; gap: 1.3rem; }
[data-nav-fit-panel] .nav__sub {
  position: relative;
  align-items: center;
  gap: 1.1rem;
  padding-top: 1.3rem;
}
[data-nav-fit-panel] .nav__sub::before {
  content: "";
  position: absolute; top: 0; left: 50%;
  width: 28px; height: 1px;
  transform: translateX(-50%);
  background: var(--line-gold);
}
[data-nav-fit-panel] .nav__sub .nav__link { font-size: 0.85rem; }
[data-nav-fit-panel] .nav__caret { display: none; }

/* The architectural rail stays on a width breakpoint. It is a page-layout
   element, not part of the nav row, so it has no reason to follow the nav
   into the burger — and .nav's offset is the rail's, so it moves with it. */
@media (max-width: 1024px) {
  :root { --rail: 0px; }
  .rail { display: none; }
  .nav { left: 0; }

  .stats { grid-template-columns: repeat(2, 1fr); }
  .stat:nth-child(3) { border-left: none; }
}

@media (max-width: 880px) {
  .split, .split--portrait { grid-template-columns: 1fr; gap: 2.5rem; }
  .split__media { order: -1; }
  .estate, .estate:nth-child(even) .estate__media { grid-template-columns: 1fr; }
  .estate:nth-child(even) .estate__media { order: -1; }
  .estate__media { order: -1; }

  .quotes--row { grid-template-columns: 1fr; }
  .feature-grid { grid-template-columns: 1fr; }
  .guide { grid-template-columns: 1fr; }
  .footer__top { grid-template-columns: 1fr; gap: 2.5rem; }
  .contact-grid { grid-template-columns: 1fr; }

  .service { grid-template-columns: auto 1fr; column-gap: 1.2rem; row-gap: 1.3rem; align-items: center; }
  .service:hover { padding-left: 0; }
  .service__no { grid-column: 1; grid-row: 1; font-size: 1.5rem; }
  .service__link { grid-column: 2; grid-row: 1; justify-self: end; width: 46px; height: 46px; }
  .service__body { grid-column: 1 / -1; grid-row: 2; }
}

@media (max-width: 540px) {
  .stats { grid-template-columns: 1fr; }
  .stat, .stat:nth-child(3) { border-left: none; }
  .tl-item { grid-template-columns: 1fr; row-gap: 0.5rem; padding-block: 1.8rem; }
  .tl-node { display: none; }
  .tl-year { font-size: 1.5rem; }
}

/* ---- Reduced motion ----------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal, .clip, .draw,
  [data-stagger] > * { opacity: 1 !important; transform: none !important; clip-path: none !important; }
  .hero__media img { height: 100%; }
}


/* =====================================================================
   ADDED IN CONVERSION — markup the source template did not have
   classic-dark
   ===================================================================== */

/* Ylopo IDX widget. It renders its own cards; this only reserves the space
   and shimmers until it hydrates, so the page does not jump.

   The gradient named --paper-2 and --card, which are classic-light's tokens and
   have never existed in this file. An undefined var() invalidates the whole
   declaration, so the shimmer was simply absent here - no error, and nothing to
   see unless you happened to catch the widget mid-hydration. Named in the dark
   surfaces instead: had those tokens ever been added, the placeholder would
   have flashed a light slab on every Home and Search page. */
.ylopo-easy-widget { min-height: 420px; position: relative; }
.ylopo-easy-widget.ylopo-loading::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, var(--ink-2) 25%, var(--ink-3) 37%, var(--ink-2) 63%);
  background-size: 400% 100%;
  animation: classic-shimmer 1.4s ease infinite;
}
.ylopo-easy-widget.ylopo-ready::before { display: none; }
@keyframes classic-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }

/* The source styled .feature h4; the converted markup uses h3, which is the
   correct level under the section's h2. */
.feature h3 {
  font-family: var(--display);
  font-size: 1.45rem;
  font-weight: 400;
}

/* The features band on Buyers and Sellers used to be grounded here, with a
   :has(.feature-grid) override that reached one of the four .section-ivory
   bands and left the other three as paper. That override is gone: the class
   itself is neutralised where it is defined, and .feature-grid / .feature
   carry their dark values in their own base rules. Both are in the theme
   section above, so each rule has one source of truth - which is what stops a
   band from being paper on one page and ink on another.

   classic-light and classic-clean are untouched by any of it: there the ivory
   band IS the design, and this file is the only thing the three themes do not
   share. */

/* QA build notices. Deliberately visible while the reviews, sold-properties
   and contact-form widgets are being built - an empty band reads as broken
   where a labelled one reads as pending. Remove once all three ship. */
.qa-note {
  display: flex; align-items: flex-start; gap: 1rem; flex-wrap: wrap;
  max-width: 60ch;
  padding: 1.4rem 1.6rem;
  border: 1px dashed var(--brass);
  border-radius: 2px;
  background: color-mix(in srgb, var(--champagne) 8%, transparent);
}
.qa-note__tag {
  flex: none;
  font-size: 0.62rem; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink);
  background: var(--champagne);
  border-radius: 2px;
  padding: 0.35rem 0.8rem;
}
.qa-note p { font-size: 0.94rem; color: var(--stone); flex: 1 1 22ch; margin: 0; }

@media (max-width: 640px) { .qa-note { flex-direction: column; gap: 0.8rem; } }

/* Mobile CTA width ----------------------------------------------------
   At phone widths a standalone CTA goes full width with its label centred.
   Sized to its own text it leaves a ragged edge against the copy above it,
   and of two stacked buttons the shorter reads as the lesser one purely
   because it is narrower.

   Card actions and widget-injected markup are excluded. Written as a
   max-width override rather than a mobile-first base rule so the desktop
   layout cannot be affected by construction. */
@media (max-width: 640px) {
  .btn { width: 100%; justify-content: center; text-align: center; }
  .community .btn,
  .ylopo-easy-widget .btn { width: auto; }

  /* "Open the full search" is a text link, not a CTA, so it is centred
     without being stretched. fit-content keeps the hover underline tight to
     the label - .tlink::after spans the element, so a full-width link would
     drag a rule across the column. */
  .tlink { display: flex; width: fit-content; margin-inline: auto; }

  /* The hero wants nothing here any more. This block used to stack .hero's
     flex row so the copy got its full measure back from the scroll indicator;
     the indicator is out of flow at every width now, .hero__inner is the only
     item in that row, and there is nothing left to stack. Re-adding a
     flex-direction here would only move the centred copy back to the floor of
     the hero on a phone. */
}

/* Sold page with nothing to show.
   The visitor-facing counterpart to .qa-note: an agent whose Ylopo agent ids
   are not on file yet gets this instead of an empty band. Which of the two
   renders is decided in Nunjucks - the widget has to be absent from the page,
   not hidden here.

   Dark theme: the body is --ivory on --ink, so the title takes --ivory and the
   accent is --champagne rather than the darker --brass, which does not carry
   enough contrast against this background. */
.sold-empty {
  max-width: 46ch; margin-inline: auto;
  padding: 2rem 1rem;
  text-align: center;
  border-top: 1px solid var(--line-light, rgba(244,240,231,0.12));
  border-bottom: 1px solid var(--line-light, rgba(244,240,231,0.12));
}
.sold-empty .sold-empty__title {
  font-family: var(--display, Georgia, serif);
  font-size: var(--fs-h3, 1.6rem); font-weight: 400;
  margin: 0 0 0.75rem;
  color: var(--ivory, #F4F0E7);
}
.sold-empty p { margin: 0; font-size: var(--fs-body, 1rem); color: var(--stone, #A39B8C); }
.sold-empty a { color: var(--champagne, #C7A763); text-decoration: underline; text-underline-offset: 0.2em; }
.sold-empty a:hover { color: var(--ivory, #F4F0E7); }

/* Sale date on sold cards - OFF unless SHOW_SOLD_DATE is on in
   scripts/feature-flags.mjs, which is what emits data-sold-date on the widget.

   The Ylopo widget puts the date in .gallery-card-b-generate-sort-block, which
   this template's card CSS in the ylopo-grid project hides outright. Overriding
   that !important needs both the flag attribute and this specificity, so the
   rule lives here rather than there - and so the per-template design of the bar,
   when it happens, sits with the rest of this template's tokens.

   :has(.sold-date) is load-bearing, not decoration. For-sale cards reuse the
   same container for "Listed 4 Months Ago", so revealing it unscoped would put
   that strip on every listing card on every home and search page. Only a sold
   card has .sold-date inside.

   Two selectors, not one: the card redesign takes .property-details-wrap out of
   layout with display:none, and on these templates that wrapper holds the sort
   block and nothing else - so the block alone computes to a 0x0 box inside a
   hidden parent. Revealing the wrapper duplicates no content precisely because
   it is otherwise empty; check that still holds before copying this to a new
   template.

   Still wearing the widget's own grey bar styling: designing it per template is
   the work that has to happen before the flag is turned on. */
.ylopo-easy-widget[data-sold-date="true"] .property-details-wrap:has(.sold-date),
.ylopo-easy-widget[data-sold-date="true"] .gallery-card-b-generate-sort-block:has(.sold-date) {
  display: flex !important;
}

/* Backdrop for the nav drawer. Created by the template's script, not by the
   layout, so no markup changes. It exists as much to swallow the click as to
   dim the page: tapping beside an open drawer should dismiss it and nothing
   else, and a dim painted with a shadow on the panel would let that tap fall
   through to a link underneath. Sits one below the drawer. */
.nav-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.45);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.45s var(--ease), visibility 0s linear 0.45s;
  z-index: 64;
}
.nav-backdrop.is-open {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}
