@charset "utf-8";
/* ==========================================================================
   Navigating North Florida — Gina Graham
   Design system. Hand-written, no frameworks.

   1.  Tokens
   2.  Reset & base
   3.  Layout primitives (wrap / section / split / rail)
   4.  Typography utilities (overline, display, prose, rules, ornament)
   5.  Buttons & links
   6.  Header, desktop nav, mobile overlay
   7.  Home hero (ambient video)
   8.  Page hero (interior pages)
   9.  Editorial trio, figures, galleries
   10. Reviews
   11. Video CTA + modal
   12. Forms (lead + newsletter)
   13. Affiliations
   14. Footer
   15. Reveal utilities + reduced motion
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
  /* --- Brand colour, sampled from the gtg marks --------------------------- */
  --navy:        #10486f;   /* monogram navy — the brand blue */
  --navy-deep:   #0a3050;   /* deep ground for dark sections */
  --navy-night:  #072134;   /* near-black navy, footer + scrims */
  --ink:         #14314a;   /* body text on light */
  --ink-soft:    #5b7085;   /* secondary text, captions */
  --ink-faint:   #8a9aa8;   /* meta, disabled */

  --shell:       #faf7f2;   /* page ground — warm ivory, never pure white */
  --shell-warm:  #f2ebe1;   /* alternate band */
  --shell-deep:  #e7ddd0;   /* hairline-adjacent tint */
  --paper:       #fffdfa;   /* raised surfaces */

  --aqua:        #6ec6d9;   /* script-logo aqua — accents only, never fields */
  --aqua-deep:   #3d8ea3;   /* aqua that survives a light background */
  --aqua-mist:   #e4f2f6;

  --brass:       #c09a3e;   /* wordmark gold */
  --brass-soft:  #d8b868;   /* foil highlight, use on dark */
  --brass-deep:  #7a5c1e;   /* brass that reads as text on ivory and the warm band (4.6:1) */

  --line:        rgba(20, 49, 74, 0.14);
  --line-strong: rgba(20, 49, 74, 0.28);
  --line-brass:  rgba(192, 154, 62, 0.55);
  --line-light:  rgba(250, 247, 242, 0.24);

  /* --- Type -------------------------------------------------------------- */
  --font-display: "Cormorant Garamond", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
  --font-sans: "Jost", "Avenir Next", "Segoe UI", system-ui, -apple-system, sans-serif;

  --fs-display: clamp(3.4rem, 12vw, 9.5rem);
  --fs-h1:      clamp(2.5rem, 6vw, 4.5rem);
  --fs-h2:      clamp(2rem, 4.3vw, 3.35rem);
  --fs-h3:      clamp(1.45rem, 2.4vw, 2.05rem);
  --fs-h4:      clamp(1.15rem, 1.6vw, 1.4rem);
  --fs-lede:    clamp(1.08rem, 1.35vw, 1.3rem);
  --fs-body:    1.0625rem;
  --fs-small:   0.9rem;
  --fs-overline: 0.72rem;

  --track-overline: 0.22em;
  --track-caps: 0.16em;

  /* --- Space ------------------------------------------------------------- */
  --sp-1: 0.5rem;
  --sp-2: 0.75rem;
  --sp-3: 1rem;
  --sp-4: 1.5rem;
  --sp-5: 2rem;
  --sp-6: 3rem;
  --sp-7: 4.5rem;
  --sp-8: 6.5rem;

  --section-y:  clamp(4.5rem, 9vw, 9rem);
  --gutter:     clamp(1.25rem, 5vw, 3.5rem);

  --wrap:        1240px;
  --wrap-wide:   1520px;
  --wrap-narrow: 720px;

  --header-h: 88px;

  --ease: cubic-bezier(0.22, 0.61, 0.24, 1);
  --dur:  0.5s;

  --shadow-soft: 0 24px 60px -30px rgba(7, 33, 52, 0.45);
  --shadow-lift: 0 40px 90px -40px rgba(7, 33, 52, 0.6);
}

/* ==========================================================================
   2. RESET & BASE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
}

body {
  margin: 0;
  background: var(--shell);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

h1, h2, h3, h4, h5, h6 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.08;
  letter-spacing: -0.01em;
  color: var(--navy);
}

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

ul, ol { margin: 0; padding: 0; }

img, video, svg { max-width: 100%; display: block; }
img { height: auto; }

a { color: var(--navy); text-decoration: none; }

button { font: inherit; color: inherit; }

hr { border: 0; height: 1px; background: var(--line); margin: var(--sp-6) 0; }

:focus-visible {
  outline: 2px solid var(--aqua-deep);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection { background: var(--aqua); color: var(--navy-night); }

.skip-link {
  position: absolute;
  left: 1rem;
  top: -100px;
  z-index: 200;
  background: var(--navy);
  color: var(--shell);
  padding: 0.75rem 1.25rem;
  font-size: var(--fs-overline);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  transition: top 0.2s var(--ease);
}
.skip-link:focus { top: 1rem; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ==========================================================================
   3. LAYOUT PRIMITIVES
   ========================================================================== */

/* .wrap — the standard centred measure. Modifiers change width only. */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--wide   { max-width: var(--wrap-wide); }
.wrap--narrow { max-width: var(--wrap-narrow); }

/* .section — vertical rhythm unit. Every band on every page is one. */
.section {
  position: relative;
  padding-block: var(--section-y);
}
.section--tight { padding-block: clamp(3rem, 5.5vw, 5rem); }
.section--flush-top    { padding-top: 0; }
.section--flush-bottom { padding-bottom: 0; }

/* Ground variants */
.section--shell { background: var(--shell-warm); }
.section--paper { background: var(--paper); }
.section--ink {
  background: var(--navy-deep);
  color: rgba(250, 247, 242, 0.82);
}
.section--ink h1, .section--ink h2, .section--ink h3,
.section--ink h4, .section--ink h5 { color: var(--shell); }
.section--ink a { color: var(--aqua); }
.section--ink .overline { color: var(--brass-soft); }
.section--ink .rule { background: var(--line-brass); }

/* .section--media — full-bleed photograph behind content.
   Put the <img> in .section__bg and the copy in a .wrap. */
.section--media {
  color: rgba(250, 247, 242, 0.9);
  isolation: isolate;
}
.section--media h1, .section--media h2, .section--media h3,
.section--media h4 { color: var(--shell); }
.section--media .overline { color: var(--brass-soft); }

.section__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  overflow: hidden;
}
.section__bg img {
  width: 100%; height: 100%;
  object-fit: cover;
}
/* Scrim keeps type legible over any photograph. */
.section__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(7,33,52,0.78) 0%, rgba(7,33,52,0.62) 55%, rgba(10,48,80,0.8) 100%);
}
.section__bg--soft::after {
  background: linear-gradient(180deg, rgba(7,33,52,0.5) 0%, rgba(7,33,52,0.72) 100%);
}

/* .split — the workhorse asymmetric two-column. 7/5 by default.
   .split--reverse puts media on the right; .split--even is 1:1;
   .split--wide-media is 8/4 for hero-scale photography. */
.split {
  display: grid;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
}
@media (min-width: 900px) {
  .split { grid-template-columns: 7fr 5fr; }
  .split--even       { grid-template-columns: 1fr 1fr; }
  .split--wide-media { grid-template-columns: 8fr 4fr; }
  .split--narrow-media { grid-template-columns: 5fr 7fr; }
  .split--reverse .split__media { order: 2; }
  .split--reverse .split__body  { order: 1; }
  .split--top { align-items: start; }
}
.split__body { max-width: 46ch; }
.split--even .split__body,
.split--narrow-media .split__body { max-width: 52ch; }

/* .split--offset — media bleeds past the container on its outer edge and the
   body overlaps it slightly. The editorial look; desktop only. */
@media (min-width: 1100px) {
  .split--offset .split__media { margin-left: calc(var(--gutter) * -1 - 2vw); }
  .split--offset.split--reverse .split__media {
    margin-left: 0;
    margin-right: calc(var(--gutter) * -1 - 2vw);
  }
  .split--offset .split__body { margin-left: -3rem; }
  .split--offset.split--reverse .split__body { margin-left: 0; margin-right: -3rem; }
}

/* .rail — horizontal scrolling strip for galleries. Never traps the page. */
.rail {
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--line-strong) transparent;
  padding-bottom: var(--sp-3);
}
.rail__track {
  display: flex;
  gap: clamp(0.75rem, 1.6vw, 1.5rem);
  padding-inline: var(--gutter);
  width: max-content;
}
.rail__item {
  position: relative;
  background: var(--shell);
  padding: 0.5rem;
  box-shadow: var(--shadow-soft);
  flex: 0 0 auto;
  width: clamp(220px, 30vw, 400px);
  scroll-snap-align: center;
}
.rail__item img {
  width: 100%;
  height: clamp(180px, 24vw, 320px);
  object-fit: cover;
}
.rail__item--tall img { height: clamp(230px, 30vw, 400px); }
.rail::-webkit-scrollbar { height: 3px; }
.rail::-webkit-scrollbar-thumb { background: var(--line-strong); }

/* ==========================================================================
   4. TYPOGRAPHY UTILITIES
   ========================================================================== */

/* .overline — letterspaced small caps label. Sits above headings. */
.overline {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin: 0 0 var(--sp-3);
  font-family: var(--font-sans);
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-overline);
  text-transform: uppercase;
  color: var(--brass-deep);
  line-height: 1.4;
}
.overline::before {
  content: "";
  flex: 0 0 auto;
  width: 2.25rem;
  height: 1px;
  background: currentColor;
  opacity: 0.65;
}
.overline--bare::before { display: none; }
.overline--center { justify-content: center; }

/* .display — the hero lockup scale. One per page, in the hero only. */
.display {
  font-size: var(--fs-display);
  font-weight: 400;
  line-height: 0.86;
  letter-spacing: -0.025em;
}

.headline   { font-size: var(--fs-h2); }
.headline--lg { font-size: var(--fs-h1); }
.subhead {
  font-size: var(--fs-h3);
  font-style: italic;
  font-weight: 400;
  color: var(--navy);
}
.section--ink .subhead, .section--media .subhead { color: var(--aqua); }

/* .lede — the one larger paragraph directly under a heading. */
.lede {
  font-size: var(--fs-lede);
  font-weight: 300;
  line-height: 1.7;
  color: var(--ink);
}
.section--ink .lede, .section--media .lede { color: rgba(250,247,242,0.9); }

/* .prose — body copy blocks; sets a comfortable measure. */
.prose { max-width: 62ch; }
.prose p + p { margin-top: 0; }
.prose > * + h3, .prose > * + h4 { margin-top: var(--sp-5); }

/* .rule — thin brass hairline used as a divider or under a heading. */
.rule {
  width: 4.5rem;
  height: 1px;
  border: 0;
  margin: var(--sp-4) 0;
  background: var(--brass);
  opacity: 0.8;
}
.rule--full { width: 100%; background: var(--line); }
.rule--center { margin-inline: auto; }

/* .ornament — the gtg monogram used as a small section mark. */
.ornament {
  width: 44px;
  height: 44px;
  margin: 0 0 var(--sp-4);
  opacity: 0.9;
}
.ornament--center { margin-inline: auto; }

.text-center { text-align: center; }
.text-center .overline { justify-content: center; }
.text-center .prose, .text-center .lede { margin-inline: auto; }

.stack > * + * { margin-top: var(--sp-4); }

/* ==========================================================================
   5. BUTTONS & LINKS
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.95rem 1.9rem;
  border: 1px solid var(--navy);
  background: transparent;
  color: var(--navy);
  font-family: var(--font-sans);
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
              color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.btn:hover, .btn:focus-visible {
  background: var(--navy);
  color: var(--shell);
  border-color: var(--navy);
}

.btn--solid {
  background: var(--navy);
  color: var(--shell);
}
.btn--solid:hover, .btn--solid:focus-visible {
  background: var(--brass-deep);
  border-color: var(--brass-deep);
  color: var(--shell);
}

/* .btn--light — for dark grounds (ink sections, media scrims, hero). */
.btn--light {
  border-color: rgba(250, 247, 242, 0.7);
  color: var(--shell);
}
.btn--light:hover, .btn--light:focus-visible {
  background: var(--shell);
  color: var(--navy);
  border-color: var(--shell);
}

.btn--brass { border-color: var(--brass); color: var(--brass-deep); }
.btn--brass:hover, .btn--brass:focus-visible {
  background: var(--brass); border-color: var(--brass); color: var(--navy-night);
}


.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}

/* .link-quiet — inline text link with a brass underline on hover. */
.link-quiet {
  color: inherit;
  border-bottom: 1px solid var(--line-brass);
  padding-bottom: 1px;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.link-quiet:hover { border-bottom-color: var(--brass); color: var(--brass-deep); }
.section--ink .link-quiet:hover, .section--media .link-quiet:hover { color: var(--brass-soft); }

/* ==========================================================================
   6. HEADER / NAV
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 90;
  background: var(--shell);
  border-bottom: 1px solid var(--line);
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}

/* .site-header--overlay — home page only: sits on the hero until scrolled. */
.site-header--overlay {
  position: fixed;
  left: 0; right: 0;
}
/* The transparent state exists only while script runs. Without it the header
   is the solid one, so nothing ever sits ivory on ivory. */
.js .site-header--overlay {
  background: transparent;
  border-bottom-color: transparent;
}
.js .site-header--overlay .nav__link,
.js .site-header--overlay .nav-toggle { color: var(--shell); }
.js .site-header--overlay .header__logo img { filter: drop-shadow(0 2px 12px rgba(7,33,52,0.55)); }
.site-header--overlay.is-stuck {
  background: rgba(250, 247, 242, 0.96);
  backdrop-filter: saturate(1.1) blur(6px);
  border-bottom-color: var(--line);
}
.site-header--overlay.is-stuck .nav__link,
.site-header--overlay.is-stuck .nav-toggle { color: var(--ink); }
.site-header--overlay.is-stuck .header__logo img { filter: none; }

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: var(--header-h);
}

/* The mark can shrink below its set width rather than push the hamburger off
   the bar; on a 320px screen that is the only thing between the lockup and a
   horizontal scrollbar. */
.header__logo { display: block; flex: 0 1 auto; min-width: 0; line-height: 0; }
.header__mark { display: block; width: 368px; max-width: 100%; height: auto; }

@media (max-width: 640px) {
  .header__mark { width: 272px; }
  :root { --header-h: 72px; }
}

.nav { display: none; }
@media (min-width: 1080px) { .nav { display: block; } }

.nav__list {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 1.7vw, 1.75rem);
  list-style: none;
}

.nav__link {
  position: relative;
  display: block;
  padding: 0.4rem 0;
  font-size: var(--fs-overline);
  font-weight: 400;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
  transition: color var(--dur) var(--ease);
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--brass);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur) var(--ease);
}
.nav__link:hover::after,
.nav__link:focus-visible::after,
.nav__link[aria-current="page"]::after { transform: scaleX(1); }
.nav__link[aria-current="page"] { color: var(--brass-deep); }
.site-header--overlay .nav__link[aria-current="page"] { color: var(--brass-soft); }
.site-header--overlay.is-stuck .nav__link[aria-current="page"] { color: var(--brass-deep); }

/* Hamburger. `flex: 0 0 auto` because it is the tap target, and a 44px tap
   target that shrinks is not one: once the mark next to it became shrinkable
   in round 6, the default `flex-shrink: 1` let the row take the difference out
   of both, and this fell to 38px at 320. Only the mark gives ground now. */
.nav-toggle {
  display: inline-flex;
  flex: 0 0 auto;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  width: 44px; height: 44px;
  padding: 0 8px;
  border: 0;
  background: none;
  color: var(--ink);
  cursor: pointer;
}
@media (min-width: 1080px) { .nav-toggle { display: none; } }
.nav-toggle span {
  display: block;
  height: 1px;
  background: currentColor;
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.nav-toggle span:nth-child(1) { width: 100%; }
.nav-toggle span:nth-child(2) { width: 70%; margin-left: auto; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(3.5px) rotate(10deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { width: 100%; transform: translateY(-3.5px) rotate(-10deg); }

/* Full-screen overlay menu */
.nav-overlay {
  position: fixed;
  inset: 0;
  z-index: 95;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: calc(var(--header-h) + 2rem) var(--gutter) 3rem;
  background: var(--navy-deep);
  color: var(--shell);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-1.5rem);
  transition: opacity 0.45s var(--ease), transform 0.45s var(--ease), visibility 0.45s;
  overflow-y: auto;
}
.nav-overlay.is-open { opacity: 1; visibility: visible; transform: none; }

.nav-overlay__close {
  position: absolute;
  top: max(1rem, calc((var(--header-h) - 44px) / 2));
  right: var(--gutter);
  width: 44px; height: 44px;
  border: 0;
  background: none;
  color: var(--shell);
  font-size: 1.7rem;
  line-height: 1;
  cursor: pointer;
}

.nav-overlay__list { list-style: none; }
.nav-overlay__list li + li { margin-top: 0.35rem; }
.nav-overlay__link {
  display: inline-block;
  padding: 0.28rem 0;
  font-family: var(--font-display);
  font-size: clamp(1.85rem, 7vw, 2.6rem);
  font-weight: 400;
  line-height: 1.15;
  color: var(--shell);
  transition: color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.nav-overlay__link:hover,
.nav-overlay__link:focus-visible { color: var(--aqua); transform: translateX(6px); }
.nav-overlay__link[aria-current="page"] { color: var(--brass-soft); font-style: italic; }

.nav-overlay__foot {
  margin-top: var(--sp-6);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-light);
  font-size: var(--fs-small);
  color: rgba(250, 247, 242, 0.7);
}
.nav-overlay__foot a { color: var(--aqua); }

/* ==========================================================================
   7. HOME HERO
   ========================================================================== */

.hero {
  position: relative;
  min-height: min(100svh, 900px);
  display: flex;
  align-items: flex-end;
  isolation: isolate;
  background: var(--navy-night);
  color: var(--shell);
  overflow: hidden;
}

.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img,
.hero__media video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.hero__video {
  opacity: 0;
  transition: opacity 1.6s var(--ease);
}
.hero__video.is-playing { opacity: 1; }

/* Invisible marker at the top of the page; the overlay header flips to its
   solid state once this scrolls out of view. */
.header-sentinel {
  position: absolute;
  top: 0; left: 0;
  width: 1px; height: 1px;
  pointer-events: none;
}

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg, rgba(7,33,52,0.62) 0%, rgba(7,33,52,0.18) 38%, rgba(7,33,52,0.86) 100%),
    linear-gradient(90deg, rgba(7,33,52,0.55) 0%, rgba(7,33,52,0) 62%);
}

.hero__inner {
  width: 100%;
  padding-top: calc(var(--header-h) + clamp(4rem, 14vh, 9rem));
  padding-bottom: clamp(2.5rem, 7vh, 5rem);
}

/* The three-part display lockup: script-ish italic / caps / large roman. */
.hero__lockup { margin: 0; color: var(--shell); }
.hero__line-1 {
  display: block;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.3rem, 7vw, 5.4rem);
  line-height: 0.95;
  letter-spacing: -0.015em;
  margin-left: 0.06em;
}
.hero__line-2 {
  display: block;
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: clamp(0.78rem, 1.6vw, 1.05rem);
  letter-spacing: 0.52em;
  text-transform: uppercase;
  margin: clamp(0.6rem, 1.4vw, 1.1rem) 0 clamp(0.2rem, 0.8vw, 0.6rem);
  padding-left: 0.3em;
  color: rgba(250, 247, 242, 0.92);
}
.hero__line-3 {
  display: block;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-display);
  line-height: 0.8;
  letter-spacing: -0.035em;
}

/* The CTA row is the button alone again. Round 5 put the combined lockup in
   here below 1080 because the header only carried it from 1080 up, and hid it
   above that on the rule that showing the brokerage twice on one screen says
   it twice. Round 6 carries the lockup in the header at every width, so the
   same rule now empties the hero: the two sat one above the other on a phone,
   the same drawing in the same colourway, about 470px apart. The header is
   sticky, so the brokerage is nearer the top than the hero pairing ever was.
   `.hero__brokerage` and `.hero__brokerage-lockup` are gone with it; putting
   the pairing back is the one <p> in index.html and these two rules. */
.hero__cta {
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 3.5vw, 2.75rem);
  flex-wrap: wrap;
}

/* Neighbourhood links across the foot of the hero. */
.hero__places {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: clamp(1rem, 3.5vw, 3rem);
  list-style: none;
  margin-top: clamp(2.5rem, 6vh, 4.5rem);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-light);
}
.hero__places a {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.15rem, 2.1vw, 1.6rem);
  color: rgba(250, 247, 242, 0.86);
  transition: color var(--dur) var(--ease);
}
.hero__places a:hover, .hero__places a:focus-visible { color: var(--aqua); }

/* Below 768 the four names are a fixed two by two rather than a row that wraps
   where it happens to run out. This is a layout-shift fix, not a taste one.
   The names are set in the display italic, and Georgia, the fallback the page
   paints with before Cormorant arrives, is wider: with the fallback the row
   wraps to two lines at every phone width, and with Cormorant loaded it drops
   to one from 356px up. The row therefore collapsed from 105px to 57px at the
   font swap, and because `.hero` is `align-items: flex-end` under a
   `min(62svh, 620px)` floor, losing 48px took the inner from 516 to 468, under
   the floor, so flex-end pushed the whole hero content down 35px. Measured on
   the home page that was a CLS of 0.295 at 360, 375 and 390.

   Reserving a height and clipping would fix the number and risk the content:
   the one-line layout only just fits, 313px of text in a 316px row at 356px,
   so a reserved 57px is three pixels from cutting a name in half on a slightly
   different build of the font. A grid of two columns cannot collapse instead
   of wrapping, so both font states are two rows and the only movement left is
   the line-height difference between the two faces. That is what 320px already
   did, where the fallback and the loaded font both wrapped and CLS was 0.003.
   Measured after: 0.009 at 360, 0.009 at 375, 0.009 at 390, and nothing is
   ever hidden, so a longer list of neighbourhoods simply makes the block
   taller. From 768 up the row is one line in both faces and stays a flex row. */
@media (max-width: 767px) {
  .hero__places {
    display: grid;
    grid-template-columns: repeat(2, max-content);
    justify-content: start;
  }
}

.hero__scroll {
  position: absolute;
  right: var(--gutter);
  bottom: clamp(2.5rem, 7vh, 5rem);
  z-index: 1;
  display: none;
  align-items: center;
  gap: 0.75rem;
  font-size: var(--fs-overline);
  letter-spacing: var(--track-overline);
  text-transform: uppercase;
  color: rgba(250, 247, 242, 0.72);
}
@media (min-width: 1080px) { .hero__scroll { display: flex; } }
.hero__scroll::after {
  content: "";
  width: 1px; height: 3.5rem;
  background: linear-gradient(180deg, rgba(250,247,242,0.7), rgba(250,247,242,0));
}

/* ==========================================================================
   8. PAGE HERO (interior pages)
   ========================================================================== */

.page-hero {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  min-height: clamp(320px, 46vh, 520px);
  background: var(--navy-deep);
  color: var(--shell);
  overflow: hidden;
}
.page-hero__media { position: absolute; inset: 0; z-index: -2; }
.page-hero__media img { width: 100%; height: 100%; object-fit: cover; }
.page-hero::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(7,33,52,0.62) 0%, rgba(7,33,52,0.3) 45%, rgba(7,33,52,0.85) 100%);
}
.page-hero__inner {
  width: 100%;
  padding-block: clamp(3rem, 8vh, 5.5rem);
}
.page-hero__title {
  font-size: var(--fs-h1);
  color: var(--shell);
  max-width: 18ch;
}
.page-hero .overline { color: var(--brass-soft); }
.page-hero__lede {
  margin-top: var(--sp-4);
  max-width: 52ch;
  font-size: var(--fs-lede);
  font-weight: 300;
  color: rgba(250, 247, 242, 0.88);
}
/* Plain variant — no photograph, ivory ground, for text-first pages. */
.page-hero--plain {
  min-height: 0;
  background: var(--shell-warm);
  color: var(--ink);
}
.page-hero--plain::before { display: none; }
.page-hero--plain .page-hero__title { color: var(--navy); }
.page-hero--plain .overline { color: var(--brass-deep); }
.page-hero--plain .page-hero__lede { color: var(--ink); }

/* Breadcrumb */
.crumbs {
  display: flex; flex-wrap: wrap; gap: 0.5rem;
  list-style: none;
  font-size: var(--fs-overline);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: var(--sp-3);
}
.crumbs li + li::before { content: "/"; margin-right: 0.5rem; opacity: 0.5; }
.page-hero .crumbs { color: rgba(250, 247, 242, 0.7); }
.page-hero .crumbs a { color: inherit; }

/* ==========================================================================
   9. FIGURES, EDITORIAL TRIO, GALLERIES
   ========================================================================== */

/* .figure and the frame family. Every photograph on the site hangs in one of
   these; a bare rectangle is the exception, not the default.
   --framed   brass hairline offset down and right, the editorial signature
   --matted   ivory gallery mat with a hairline rule inset, for interiors
   --arch     arched top with a brass arch outline, for portraits and heroes
   --plate    navy hairline with a second brass rule outside, for small images
   Cards, rails and mosaics get the mat by default (see their own rules). */
.figure { position: relative; margin: 0; }
.figure img { display: block; width: 100%; height: auto; }

.figure--framed::before {
  content: "";
  position: absolute;
  inset: var(--frame-offset, 0.9rem) calc(-1 * var(--frame-offset, 0.9rem))
         calc(-1 * var(--frame-offset, 0.9rem)) var(--frame-offset, 0.9rem);
  border: 1px solid var(--line-brass);
  z-index: -1;
  pointer-events: none;
}
.section--ink .figure--framed::before { border-color: rgba(192, 154, 62, 0.7); }

.figure--matted {
  background: var(--shell);
  padding: clamp(0.6rem, 1.6vw, 1.1rem);
  box-shadow: var(--shadow-soft);
}
.figure--matted::after {
  content: "";
  position: absolute;
  inset: 0.35rem;
  border: 1px solid var(--line);
  pointer-events: none;
}
.section--ink .figure--matted { background: rgba(250, 247, 242, 0.96); }

.figure--arch img { border-radius: 999px 999px 0 0; }
.figure--arch::before {
  content: "";
  position: absolute;
  inset: calc(-1 * var(--frame-offset, 0.9rem));
  border: 1px solid var(--line-brass);
  border-radius: 999px 999px 0 0;
  pointer-events: none;
}

.figure--plate img { outline: 1px solid var(--navy); outline-offset: -1px; }
.figure--plate::after {
  content: "";
  position: absolute;
  inset: -0.45rem;
  border: 1px solid var(--line-brass);
  pointer-events: none;
}

.figure--tall img { aspect-ratio: 4 / 5; object-fit: cover; }

/* .split__media--stack holds two photographs in one media column, the smaller
   one above. .figure--inset holds that one to a little over half the column and
   pushes it toward the text, so it reads as an inset portrait under the page
   hero rather than a second lead photograph. */
.split__media--stack { display: grid; gap: clamp(1.75rem, 3.5vw, 3rem); }
.split__media--stack .figure--inset {
  width: min(56%, 280px);
  margin-left: auto;
  margin-right: clamp(0rem, 4vw, 3rem);
}
.figure--wide img { aspect-ratio: 16 / 10; object-fit: cover; }
.figure--square img { aspect-ratio: 1 / 1; object-fit: cover; }
.figure__caption {
  margin-top: var(--sp-2);
  font-size: var(--fs-small);
  color: var(--ink-soft);
  font-style: italic;
}

/* .editorial-grid — a set of photo-led entries. Deliberately staggered so it
   never reads as a row of identical cards. Use 2 or 3 children. */
.editorial-grid {
  display: grid;
  gap: clamp(2rem, 4vw, 3.5rem);
}
@media (min-width: 820px) {
  .editorial-grid--3 { grid-template-columns: repeat(3, 1fr); align-items: start; }
  .editorial-grid--2 { grid-template-columns: repeat(2, 1fr); align-items: start; }
  .editorial-grid--3 > :nth-child(2) { margin-top: clamp(2rem, 5vw, 4.5rem); }
  .editorial-grid--3 > :nth-child(3) { margin-top: clamp(1rem, 2.5vw, 2rem); }
  .editorial-grid--2 > :nth-child(2) { margin-top: clamp(2rem, 5vw, 4rem); }
}

.editorial-item { display: block; }
.editorial-item__media {
  position: relative;
  overflow: hidden;
  margin-bottom: var(--sp-4);
  background: var(--shell);
  padding: clamp(0.5rem, 1.2vw, 0.85rem);
  box-shadow: var(--shadow-soft);
}
.editorial-item__media::after {
  content: "";
  position: absolute;
  inset: 0.3rem;
  border: 1px solid var(--line);
  pointer-events: none;
}
.editorial-item__media img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  transition: transform 1.1s var(--ease);
}
.editorial-item:hover .editorial-item__media img,
.editorial-item:focus-within .editorial-item__media img { transform: scale(1.04); }
.editorial-item__title {
  font-size: var(--fs-h3);
  margin-bottom: var(--sp-2);
}
.editorial-item__title a { color: inherit; }
.editorial-item:hover .editorial-item__title,
.editorial-item:focus-within .editorial-item__title { color: var(--brass-deep); }
.editorial-item__body { color: var(--ink-soft); font-size: var(--fs-small); line-height: 1.8; }
.editorial-item__more {
  display: inline-block;
  margin-top: var(--sp-3);
  font-size: var(--fs-overline);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--brass-deep);
  border-bottom: 1px solid var(--line-brass);
  padding-bottom: 2px;
}

/* .mosaic — asymmetric image collage for portfolio / project pages. */
.mosaic { display: grid; gap: clamp(0.75rem, 1.5vw, 1.25rem); }
@media (min-width: 780px) {
  .mosaic { grid-template-columns: repeat(6, 1fr); }
  .mosaic > * { grid-column: span 2; }
  .mosaic__wide  { grid-column: span 4; }
  .mosaic__full  { grid-column: span 6; }
  .mosaic__half  { grid-column: span 3; }
}
.mosaic > * { position: relative; background: var(--shell); padding: 0.5rem; box-shadow: var(--shadow-soft); }
.mosaic > *::after { content: ""; position: absolute; inset: 0.3rem; border: 1px solid var(--line); pointer-events: none; }
.mosaic img { width: 100%; height: 100%; object-fit: cover; }

/* ==========================================================================
   10. REVIEWS
   ========================================================================== */

/* .reviews — a wall of verbatim Google reviews. CSS columns give an
   editorial, uneven rhythm instead of a card grid. */
.reviews { columns: 1; column-gap: clamp(2rem, 4vw, 3.5rem); }
@media (min-width: 760px)  { .reviews { columns: 2; } }
@media (min-width: 1180px) { .reviews { columns: 3; } }

.review {
  break-inside: avoid;
  margin: 0 0 clamp(2rem, 3.5vw, 3rem);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-brass);
}
.review__quote {
  font-family: var(--font-display);
  font-size: clamp(1.02rem, 1.15vw, 1.16rem);
  font-weight: 400;
  line-height: 1.62;
  color: rgba(250, 247, 242, 0.9);
  margin: 0 0 var(--sp-3);
}
.section--shell .review__quote,
.section--paper .review__quote { color: var(--ink); }
.review__attrib { display: flex; flex-direction: column; gap: 0.15rem; }
.review__name {
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--brass-soft);
}
.section--shell .review__name, .section--paper .review__name { color: var(--brass-deep); }
.review__meta {
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  color: rgba(250, 247, 242, 0.55);
}
.section--shell .review__meta, .section--paper .review__meta { color: var(--ink-soft-aa); }
.review__stars { color: var(--brass-soft); letter-spacing: 0.18em; font-size: 0.8rem; }

/* Single large pull-quote, for pages that want one testimonial only. */
.pullquote {
  max-width: 44ch;
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 2.6vw, 2.15rem);
  font-style: italic;
  font-weight: 400;
  line-height: 1.35;
  color: var(--navy);
}
.section--ink .pullquote, .section--media .pullquote { color: var(--shell); }
.pullquote footer {
  margin-top: var(--sp-4);
  font-family: var(--font-sans);
  font-size: var(--fs-overline);
  font-style: normal;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--brass-deep);
}
.section--ink .pullquote footer, .section--media .pullquote footer { color: var(--brass-soft); }

/* ==========================================================================
   11. VIDEO CTA + MODAL
   ========================================================================== */

.video-cta {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  overflow: hidden;
  text-align: left;
}
.video-cta img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  transition: transform 1.2s var(--ease), filter var(--dur) var(--ease);
}
.video-cta::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(7,33,52,0.05) 40%, rgba(7,33,52,0.72) 100%);
}
.video-cta:hover img, .video-cta:focus-visible img { transform: scale(1.03); }

.video-cta__label {
  position: absolute;
  left: clamp(1.25rem, 3vw, 2.25rem);
  right: clamp(1.25rem, 3vw, 2.25rem);
  bottom: clamp(1.25rem, 3vw, 2.25rem);
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 1rem;
  color: var(--shell);
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  line-height: 1.5;
}
.video-cta__play {
  flex: 0 0 auto;
  width: 54px; height: 54px;
  border: 1px solid rgba(250, 247, 242, 0.75);
  border-radius: 50%;
  display: grid;
  place-items: center;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.video-cta__play::before {
  content: "";
  width: 0; height: 0;
  margin-left: 3px;
  border-left: 11px solid currentColor;
  border-top: 7px solid transparent;
  border-bottom: 7px solid transparent;
}
.video-cta:hover .video-cta__play,
.video-cta:focus-visible .video-cta__play { background: var(--shell); color: var(--navy); }

.modal {
  width: min(1080px, 92vw);
  max-width: none;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--shell);
  overflow: visible;
}
.modal::backdrop { background: rgba(7, 33, 52, 0.92); }
.modal[open] { animation: modal-in 0.4s var(--ease); }
@keyframes modal-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
.modal__video {
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  box-shadow: var(--shadow-lift);
}
.modal__close {
  position: absolute;
  top: -3rem; right: 0;
  width: 44px; height: 44px;
  border: 0;
  background: none;
  color: var(--shell);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
}
.modal__close:hover { color: var(--aqua); }

/* ==========================================================================
   12. FORMS
   ========================================================================== */

.form { max-width: 640px; }
.form--wide { max-width: 760px; }
.form--center { margin-inline: auto; }

.form__note {
  margin-bottom: var(--sp-4);
  font-size: var(--fs-small);
  color: var(--ink-soft);
}
.section--ink .form__note, .section--media .form__note { color: rgba(250,247,242,0.82); }

.form__grid { display: grid; gap: var(--sp-3); }
@media (min-width: 620px) {
  .form__grid--2 { grid-template-columns: 1fr 1fr; }
  .field--full { grid-column: 1 / -1; }
}

.field { display: flex; flex-direction: column; gap: 0.4rem; }
.field > label {
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-overline);
  text-transform: uppercase;
  color: var(--ink-soft);
}
.section--ink .field > label,
.section--media .field > label { color: rgba(250, 247, 242, 0.75); }

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.85rem 0.15rem;
  border: 0;
  border-bottom: 1px solid var(--line-strong);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.5;
  transition: border-color var(--dur) var(--ease);
}
.field textarea { min-height: 7.5rem; resize: vertical; }
.field select {
  appearance: none;
  padding-right: 1.75rem;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 0.65rem center, right 0.35rem center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}
.field input::placeholder, .field textarea::placeholder { color: var(--ink-faint); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-bottom-color: var(--brass);
}
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--aqua-deep);
  outline-offset: 4px;
}

.section--ink .field input,
.section--ink .field select,
.section--ink .field textarea,
.section--media .field input,
.section--media .field select,
.section--media .field textarea {
  color: var(--shell);
  border-bottom-color: rgba(250, 247, 242, 0.4);
}
.section--ink .field input::placeholder,
.section--media .field input::placeholder { color: rgba(250, 247, 242, 0.5); }
.section--ink .field input:focus,
.section--media .field input:focus { border-bottom-color: var(--brass-soft); }
.section--ink .field select option,
.section--media .field select option { color: var(--ink); }

/* Honeypot. display:none as well as off-screen. Chrome does not autofill a
   display:none field, and address autofill filling this for a real visitor is
   a worse outcome than a bot skipping a hidden field. Screen readers get
   aria-hidden on the wrapper anyway. */
.hp {
  display: none !important;
  position: absolute !important;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

.form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
  margin-top: var(--sp-5);
}

.form__status {
  margin: 0;
  min-height: 1.5em;
  font-size: var(--fs-small);
  line-height: 1.5;
}
.form__status:empty { min-height: 0; }
.form__status[data-state="ok"]   { color: var(--aqua-deep); }
.form__status[data-state="error"]{ color: #b1442f; }
.section--ink .form__status[data-state="ok"],
.section--media .form__status[data-state="ok"] { color: var(--aqua); }
.section--ink .form__status[data-state="error"],
.section--media .form__status[data-state="error"] { color: #f0a493; }

.form.is-sending .btn { opacity: 0.6; pointer-events: none; }

/* Newsletter band */
.newsletter { position: relative; isolation: isolate; }
.newsletter .form { max-width: 620px; }

/* ==========================================================================
   13. AFFILIATIONS
   ========================================================================== */

.affiliations {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(2rem, 6vw, 5rem);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
}
.affiliations img {
  height: clamp(46px, 6vw, 66px);
  width: auto;
  filter: grayscale(1);
  opacity: 0.62;
  transition: filter var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.affiliations img:hover { filter: none; opacity: 1; }

/* Social icon row */
.social-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  list-style: none;
  margin-top: var(--sp-5);
}
.social-row a {
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  color: var(--navy);
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}
.social-row a:hover, .social-row a:focus-visible {
  background: var(--navy); border-color: var(--navy); color: var(--shell);
}
.social-row svg { width: 17px; height: 17px; fill: currentColor; }
.section--ink .social-row a, .site-footer .social-row a {
  border-color: var(--line-light);
  color: var(--shell);
}
.section--ink .social-row a:hover, .site-footer .social-row a:hover,
.section--ink .social-row a:focus-visible, .site-footer .social-row a:focus-visible {
  background: var(--brass); border-color: var(--brass); color: var(--navy-night);
}

/* ==========================================================================
   14. FOOTER
   ========================================================================== */

.site-footer {
  background: var(--navy-night);
  color: rgba(250, 247, 242, 0.72);
  font-size: var(--fs-small);
  padding-top: clamp(2.25rem, 4.5vw, 3.25rem);
}
.site-footer h2, .site-footer h3 { color: var(--shell); }
.site-footer a { color: rgba(250, 247, 242, 0.82); transition: color var(--dur) var(--ease); }
.site-footer a:hover, .site-footer a:focus-visible { color: var(--aqua); }

/* One row: brand, Explore, Reach Me At, then the affiliation marks bottom right.
   The disclaimer runs in two small columns under a hairline; the copyright line
   closes it. Kept short on purpose: the footer is punctuation, not a page. */
.footer__top {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  padding-bottom: clamp(1.5rem, 3vw, 2rem);
  border-bottom: 1px solid var(--line-light);
  align-items: start;
}
/* Phones stack; the Explore menu is already two columns wide. */
.footer__top { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 640px) {
  .footer__top { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .footer__top > .footer__badges { grid-column: 1 / -1; }
}
@media (min-width: 1000px) {
  /* The contact column carries the brokerage name and address as well as the
     phone and the email now, so it takes the width the brand column can spare. */
  .footer__top { grid-template-columns: 1.2fr 0.95fr 1.5fr auto; }
  .footer__top > .footer__badges { grid-column: auto; align-self: end; justify-self: end; }
}

/* The mark links home. An inline anchor around a lone image draws its
   focus ring off the font metrics, so the ring lands beside the logo instead
   of around it; the anchor takes the image's own box instead. `vertical-align`
   holds the old baseline (without it the paragraph below drops 8px), and the
   gap under the mark moves from the image to the link so the ring closes
   on the mark rather than on the space below it. */
.footer__logo-link {
  display: inline-block;
  line-height: 0;
  vertical-align: bottom;
  margin-bottom: var(--sp-2);
  max-width: 100%;
}
/* Round 6: the on-dark lockup in place of her wordmark alone. 280px is the
   width at which her half of the drawing reads at the 170px the wordmark read
   at, and it is what a phone gives: the brand column is 335px at 375. A
   desktop gives less, not more, because the column shares the row with the
   Explore menu and the contact block, so from 1000px up the column's own
   241px caps it and her half reads a shade smaller there than on a phone.
   That is the right way round: the desktop header carries the lockup at 360px
   a few hundred pixels above it. */
.footer__logo { width: min(100%, 280px); height: auto; margin-bottom: var(--sp-2); }
.footer__logo-link .footer__logo { margin-bottom: 0; }
.footer__top > div:first-child p { margin: 0 0 var(--sp-3); line-height: 1.55; }
.footer__top .social-row { margin: 0; }

.footer__heading {
  font-family: var(--font-sans);
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-overline);
  text-transform: uppercase;
  color: var(--brass-soft);
  margin-bottom: var(--sp-2);
}

.footer__menu {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, max-content);
  column-gap: var(--sp-4);
  row-gap: 0.4rem;
}
.footer__menu li + li { margin-top: 0; }
.footer__menu a {
  font-size: var(--fs-overline);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

.footer__contact { list-style: none; }
.footer__contact li + li { margin-top: 0.3rem; }
.footer__contact .footer__name {
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  color: var(--shell);
  line-height: 1.15;
  margin-bottom: 0.15rem;
}

.footer__badges {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.footer__badges img {
  height: 40px;
  width: auto;
  background: var(--shell);
  padding: 4px 6px;
  opacity: 1;
}
/* The Herron mark is a white lockup on transparent, so it needs no ivory chip
   on the navy. Its box is taller than the Houzz tile because only the lower
   third of it is type; at this height the two read as one row. */
.footer__badges img.footer__badge--herron {
  height: 54px;
  background: none;
  padding: 0;
}
/* The brokerage lines are long, so they break at the middot rather than
   inside the address or the phrase. */
.footer__hold { white-space: nowrap; }

/* The Equal Housing Opportunity mark is drawn white on transparent like the
   Herron lockup, so it takes no chip either. It is square and all of it is
   drawing, so it sits at the Houzz tile's height and the three read as one row. */
.footer__badges img.footer__badge--eho {
  height: 40px;
  background: none;
  padding: 0;
}

.footer__legal {
  padding-block: clamp(1rem, 2vw, 1.4rem);
  border-bottom: 1px solid var(--line-light);
  font-size: 0.72rem;
  line-height: 1.55;
  color: rgba(250, 247, 242, 0.5);
  max-width: none;
  columns: 2;
  column-gap: var(--sp-6);
}
@media (max-width: 760px) { .footer__legal { columns: 1; } }

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-block: 0.9rem clamp(1.1rem, 2vw, 1.5rem);
  font-size: 0.74rem;
  color: rgba(250, 247, 242, 0.5);
}
.footer__bottom p { margin: 0; }
.footer__top-link {
  font-size: var(--fs-overline);
  letter-spacing: var(--track-overline);
  text-transform: uppercase;
}

/* ==========================================================================
   15. REVEAL UTILITIES + REDUCED MOTION
   ========================================================================== */

/* Nothing hides unless JS is running — no-JS visitors see everything. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.95s var(--ease), transform 0.95s var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
.js [data-reveal="fade"] { transform: none; }
.js [data-reveal="left"]  { transform: translateX(-26px); }
.js [data-reveal="right"] { transform: translateX(26px); }
.js [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;
}

@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;
    scroll-behavior: auto !important;
  }
  .js [data-reveal] { opacity: 1 !important; transform: none !important; }
  .hero__video { display: none; }
  .editorial-item__media img, .video-cta img { transition: none; }
}

/* Print — keep the contact details usable on paper. */
@media print {
  .site-header, .nav-overlay, .hero__media, .modal, .video-cta, .rail { display: none !important; }
  body { background: #fff; color: #000; }
  .section { padding-block: 1.5rem; }
}

/* ==========================================================================
   ===== Buying, Selling, Design Services (lane-services) =====
   Appended by the services lane. Nothing above this line was touched.
   ========================================================================== */

/* --- B14 -----------------------------------------------------------------
   `style="list-style:none"` inline strips list semantics in VoiceOver. The
   markup now carries role="list" and this class instead. */
.list-plain {
  list-style: none;
  padding-left: 0;
  margin: 0;
}

/* --- C7 ------------------------------------------------------------------
   The stagger only fired on the second child, so a four-item two-column grid
   offset row one and left row two flat. Genuinely global: every other page
   using .editorial-grid--2 has exactly two children, where :nth-child(even)
   and :nth-child(2) select the same element, so those pages are unchanged. */
@media (min-width: 820px) {
  .editorial-grid--2 > :nth-child(even) { margin-top: clamp(2rem, 5vw, 4rem); }
}

/* --- Required-field marker (B13) ---------------------------------------- */
.req {
  color: var(--brass-deep);
  font-weight: 500;
}
.section--ink .req, .section--media .req { color: var(--brass-soft); }

/* --- C2: rate list -------------------------------------------------------
   Replaces the <br> wall on Design Services. Name in Cormorant, description
   in Jost, price aligned right on the name's baseline, brass hairlines
   between rows. */
.rates {
  display: grid;
  gap: clamp(2.5rem, 5vw, 4rem);
}
@media (min-width: 900px) {
  .rates { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(3rem, 5vw, 5rem); }
}
.rates__group { margin: 0; }
.rates__title { margin: 0 0 var(--sp-3); }
.rates__lede {
  margin: 0 0 var(--sp-3);
  max-width: 46ch;
}
.rates__note {
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-small);
}

.rate-list {
  border-bottom: 1px solid var(--line-brass);
}
.rate-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  column-gap: clamp(1rem, 3vw, 2.5rem);
  row-gap: 0.35rem;
  padding: clamp(0.9rem, 1.8vw, 1.25rem) 0;
  border-top: 1px solid var(--line-brass);
}
.rate-row__name {
  grid-column: 1;
  grid-row: 1;
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 1.45vw, 1.35rem);
  font-weight: 500;
  line-height: 1.3;
  color: var(--shell);
}
.rate-row__price {
  grid-column: 2;
  grid-row: 1;
  justify-self: end;
  text-align: right;
  white-space: nowrap;
  font-family: var(--font-sans);
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--brass-soft);
}
.rate-row__desc {
  grid-column: 1;
  grid-row: 2;
  font-family: var(--font-sans);
  font-size: var(--fs-small);
  line-height: 1.6;
  color: rgba(250, 247, 242, 0.78);
}
/* Same list on a light band, should it ever move. */
.section--shell .rate-row__name,
.section--paper .rate-row__name { color: var(--navy); }
.section--shell .rate-row__price,
.section--paper .rate-row__price { color: var(--brass-deep); }
.section--shell .rate-row__desc,
.section--paper .rate-row__desc { color: var(--ink-soft); }

@media (max-width: 520px) {
  .rate-row {
    grid-template-columns: minmax(0, 1fr);
  }
  .rate-row__price { grid-column: 1; grid-row: 2; justify-self: start; text-align: left; }
  .rate-row__desc  { grid-column: 1; grid-row: 3; }
}

/* --- C9: rail scroll affordance -----------------------------------------
   A peek gradient in the band's own ivory plus quiet prev/next controls.
   No arrow glyphs, per the studio rule. */
.rail-frame {
  --rail-fade: var(--shell);
  position: relative;
}
.section--shell .rail-frame { --rail-fade: var(--shell-warm); }
.rail-frame::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: var(--sp-3);
  width: clamp(48px, 8vw, 110px);
  pointer-events: none;
  background: linear-gradient(to right, rgba(242, 235, 225, 0), var(--rail-fade) 82%);
  opacity: 1;
  transition: opacity var(--dur) var(--ease);
}
.rail-frame.is-end::after { opacity: 0; }
.rail-frame .rail:focus-visible { outline: 2px solid var(--brass-deep); outline-offset: -2px; }

.rail-nav[hidden] { display: none; }
.rail-nav {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-2);
  padding-inline: var(--gutter);
  padding-bottom: var(--sp-5);
  margin-top: var(--sp-3);
  position: relative;   /* keep the controls above the peek gradient */
  z-index: 1;
}
.rail-nav__btn {
  appearance: none;
  background: transparent;
  border: 1px solid var(--line-strong);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  padding: 0.6rem 1.2rem;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              color var(--dur) var(--ease),
              opacity var(--dur) var(--ease);
}
.rail-nav__btn:hover:not(:disabled),
.rail-nav__btn:focus-visible {
  background: var(--navy);
  border-color: var(--navy);
  color: var(--shell);
}
.rail-nav__btn:disabled {
  opacity: 0.35;
  cursor: default;
}

@media (prefers-reduced-motion: reduce) {
  .rail-frame::after, .rail-nav__btn { transition: none; }
}

/* ===== Blog cards and posts (lane-blog) ===== */

/* Blog covers are 16:9 banners with the headline set into the art, so the
   index cards get their own landscape box instead of the tall 4:5 crop the
   shared .editorial-item rule uses for portrait photography. The ratio matches
   the artwork: at 3:2 the wordmarks lost their first and last letters. */
.editorial-item--post .editorial-item__media img {
  aspect-ratio: 16 / 9;
  object-fit: cover;
  object-position: center;
}
.editorial-item--post .editorial-item__title { font-size: var(--fs-h4); }

/* Article pages. These used to be an inline <style> block repeated in the head
   of all thirteen generated pages. */
.post-hero {
  background: var(--shell-warm);
  padding: calc(var(--header-h) / 2 + 2rem) 0 3rem;
}
/* margin-block only: the figure also carries .wrap, whose margin-inline:auto
   is what centres it. */
.post__banner { margin-block: 0; }
.post__banner img {
  width: 100%;
  height: auto;
  box-shadow: var(--shadow-soft);
}
.post__body { padding-block: clamp(2.5rem, 5vw, 4.5rem); }
.post__body h2 { font-size: var(--fs-h3); margin: 2.2em 0 0.7em; }
.post__body ul { padding-left: 1.2rem; margin: 0 0 1.15em; }
.post__body li { margin-bottom: 0.45em; }
.post__body figure { margin: 2rem 0; }

/* Sources: one ordered list, publisher as the link text, no naked URLs. */
.post__sources-title {
  font-size: var(--fs-h4) !important;
  color: var(--ink-soft);
}
.post__sources {
  margin: 0;
  padding-left: 1.4rem;
  font-size: var(--fs-small);
  color: var(--ink-soft);
  line-height: 1.7;
  columns: 2;
  column-gap: clamp(1.5rem, 4vw, 3rem);
}
.post__sources li {
  margin-bottom: 0.35em;
  break-inside: avoid;
}
@media (max-width: 640px) {
  .post__sources { columns: 1; }
}

/* Pager: labels, no arrow glyphs. Underline arrives on hover and focus. */
.post__nav {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  gap: clamp(1rem, 3vw, 2rem);
  border-top: 1px solid var(--line);
  padding-top: var(--sp-5);
}
.post__nav-link {
  display: block;
  color: inherit;
}
.post__nav-link:last-child { text-align: right; }
.post__nav-label {
  display: block;
  font-size: var(--fs-overline);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--brass-deep);
  margin-bottom: 0.35em;
}
.post__nav-title {
  display: inline;
  font-size: var(--fs-small);
  line-height: 1.6;
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.post__nav-link:hover .post__nav-title,
.post__nav-link:focus-visible .post__nav-title {
  border-bottom-color: var(--brass);
  color: var(--brass-deep);
}
.post__nav-all {
  font-size: var(--fs-overline);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  align-self: center;
  white-space: nowrap;
}
@media (max-width: 640px) {
  .post__nav { grid-template-columns: 1fr; }
  .post__nav-link:last-child { text-align: left; }
  .post__nav-all { justify-self: start; order: 3; }
}

/* ===== Social and Around Town (lane-social-town) ===== */

/* .mat - a photograph in a paper mat with a brass hairline inside the mount.
   Used for the Facebook feed and the neighborhood tiles. */
.mat {
  position: relative;
  display: block;
  padding: clamp(0.55rem, 1.1vw, 0.9rem);
  background: var(--paper);
  box-shadow: var(--shadow-soft);
}
.mat::after {
  content: "";
  position: absolute;
  inset: clamp(0.24rem, 0.5vw, 0.42rem);
  border: 1px solid var(--line-brass);
  pointer-events: none;
}
.mat img { width: 100%; display: block; }

/* --- Social: profile row --------------------------------------------------
   Two links, no invented prose. The page name and handle come from source. */
.social-links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(0.5rem, 2vw, 2rem);
}
@media (min-width: 700px) { .social-links { grid-template-columns: 1fr 1fr; } }
.social-links__item {
  display: block;
  padding: clamp(1.1rem, 2vw, 1.6rem) 0;
  border-top: 1px solid var(--line-brass);
}
.social-links__label {
  display: block;
  margin-bottom: 0.45rem;
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-overline);
  text-transform: uppercase;
  color: var(--brass-deep);
}
.social-links__handle {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  line-height: 1.2;
  color: var(--navy);
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.social-links__item:hover .social-links__handle,
.social-links__item:focus-visible .social-links__handle {
  color: var(--brass-deep);
  border-bottom-color: var(--line-brass);
}

/* --- Social: the Facebook feed -------------------------------------------
   Nine posts. A twelve-column bed with deliberately uneven spans so the run
   reads as a spread rather than a wall of equal cards. */
.feed {
  display: grid;
  gap: clamp(2.25rem, 4vw, 3.5rem) clamp(2rem, 3.5vw, 3.5rem);
}
@media (min-width: 900px) {
  .feed { grid-template-columns: repeat(12, minmax(0, 1fr)); align-items: start; }
  .feed__post--w5 { grid-column: span 5; }
  .feed__post--w6 { grid-column: span 6; }
  .feed__post--w7 { grid-column: span 7; }
  .feed__post--feature {
    grid-column: span 12;
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: clamp(2rem, 3.5vw, 3.5rem);
    align-items: start;
  }
}

.feed__post {
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-brass);
}
.feed__place {
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-overline);
  text-transform: uppercase;
  color: var(--brass-deep);
}
.feed__mat { margin-bottom: var(--sp-4); }
.feed__mat img { aspect-ratio: 4 / 3; object-fit: cover; }
.feed__post--feature .feed__mat img { aspect-ratio: 3 / 2; }
.feed__body { max-width: 60ch; }
.feed__body p { margin-bottom: 0.9em; }
.feed__lead,
.feed__display {
  font-family: var(--font-display);
  font-weight: 400;
  color: var(--navy);
}
.feed__lead { font-size: var(--fs-h3); line-height: 1.28; }
.feed__display { font-size: clamp(1.7rem, 3vw, 2.4rem); line-height: 1.1; }
.feed__post--quiet { display: flex; flex-direction: column; }
.feed__post--quiet .feed__body { padding-block: clamp(1rem, 3vw, 2.5rem); }

.feed__list {
  list-style: none;
  margin: 0 0 1em;
  padding: 0;
}
.feed__list li {
  position: relative;
  padding-left: 1.6rem;
  margin-bottom: 0.5em;
}
.feed__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.85em;
  width: 0.8rem;
  height: 1px;
  background: var(--brass);
}
.feed__list--terms li { margin-bottom: 0.85em; }
.feed__term { font-weight: 500; color: var(--navy); }
.feed__list-label {
  margin: 0 0 0.5em;
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-overline);
  text-transform: uppercase;
  color: var(--ink-soft);
}
.feed__share { margin-top: 1em; }
.feed__tags {
  margin: var(--sp-3) 0 0;
  font-size: 0.78rem;
  line-height: 1.7;
  letter-spacing: 0.04em;
  color: var(--ink-soft-aa);
  overflow-wrap: anywhere;
}
.feed__meta { margin: var(--sp-4) 0 0; }
.feed__link {
  display: inline-block;
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--brass-deep);
  border-bottom: 1px solid var(--line-brass);
  padding-bottom: 2px;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.feed__link:hover, .feed__link:focus-visible {
  color: var(--navy);
  border-bottom-color: var(--brass);
}

/* --- Social: the Latest Posts index ---------------------------------------
   Ten entries as a dated index, not ten sliced cover thumbnails. */
.postindex {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}
.postindex__item {
  display: grid;
  gap: 0.2rem 2rem;
  padding: clamp(0.9rem, 1.8vw, 1.4rem) 0;
  border-bottom: 1px solid var(--line);
}
@media (min-width: 760px) {
  .postindex__item { grid-template-columns: 11rem minmax(0, 1fr); align-items: baseline; }
}
.postindex__date {
  margin: 0;
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-overline);
  text-transform: uppercase;
  color: var(--brass-deep);
}
.postindex__title {
  font-size: clamp(1.15rem, 1.7vw, 1.5rem);
  line-height: 1.25;
}
.postindex__title a {
  color: inherit;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.postindex__item:hover .postindex__title a,
.postindex__title a:focus-visible {
  color: var(--brass-deep);
  border-bottom-color: var(--line-brass);
}

/* --- Around Town: hero title ---------------------------------------------
   The source heading is a full sentence, so it sets a step smaller. */
.page-hero__title--long { font-size: var(--fs-h2); max-width: 26ch; }

/* --- Around Town: neighborhood picker ------------------------------------ */
.hood-tiles {
  list-style: none;
  margin: var(--sp-5) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.5vw, 2rem);
}
@media (min-width: 1000px) {
  .hood-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .hood-tiles > :nth-child(even) { margin-top: clamp(1rem, 2.5vw, 2.5rem); }
}
.hood-tile { display: block; }
.hood-tile__mat img { aspect-ratio: 4 / 5; object-fit: cover; }
.hood-tile .mat { transition: box-shadow var(--dur) var(--ease); }
.hood-tile:hover .mat, .hood-tile:focus-visible .mat { box-shadow: var(--shadow-lift); }
.hood-tile__name {
  display: block;
  margin-top: var(--sp-3);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  line-height: 1.2;
  color: var(--navy);
  text-underline-offset: 6px;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--line-brass);
}
.hood-tile:hover .hood-tile__name,
.hood-tile:focus-visible .hood-tile__name {
  color: var(--brass-deep);
  text-decoration-line: underline;
}

/* --- Around Town: neighborhood blocks ------------------------------------
   Alternating sides, and the photo column sticks so a long text column no
   longer leaves half a screen of empty ivory beside it. */
.hood { display: grid; gap: clamp(2rem, 4vw, 3.5rem); }
@media (min-width: 1000px) {
  .hood { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  .hood--reverse .hood__media { order: -1; }
  .hood__media {
    position: sticky;
    top: calc(var(--header-h) + 2rem);
    align-self: start;
  }
}
.hood__body .prose { max-width: 64ch; }
.hood__media .mat img { aspect-ratio: 3 / 2; object-fit: cover; }
@media (min-width: 1000px) { .hood__media .mat img { aspect-ratio: 4 / 5; } }
.hood__pull {
  margin: var(--sp-5) 0 0;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-brass);
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.15rem, 1.6vw, 1.45rem);
  line-height: 1.4;
  color: var(--navy);
}
.hood__list { list-style: none; margin: 0; padding: 0; }
.hood__list li {
  position: relative;
  padding-left: 1.6rem;
  margin-bottom: 0.4em;
}
.hood__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.85em;
  width: 0.8rem;
  height: 1px;
  background: var(--brass);
}

/* ===== Home, About, Contact, Portfolio (lane-home-portfolio) ===== */

/* --------------------------------------------------------------------------
   Buttons. The decorative arrow spans are gone (B8), so the hover state now
   carries a brass edge as well as the fill; that is what tells you a button
   is live. `.btn-row--center` replaces the inline justify-content that used
   to sit on centred CTA rows.
   -------------------------------------------------------------------------- */

.btn-row--center { justify-content: center; }

.btn:hover, .btn:focus-visible,
.btn--solid:hover, .btn--solid:focus-visible,
.btn--light:hover, .btn--light:focus-visible { border-color: var(--brass); }

/* --------------------------------------------------------------------------
   Gold eyebrows over photography (B14). The brass-soft label measured about
   2.8:1 at 11.5px on a scrimmed photo. Two changes together: the page-hero
   scrim ramps up earlier so it is about 0.76 opaque where the label sits, and
   the label is a lighter gold a shade larger. Sampled off the rendered pixels,
   the worst case is now 5.1:1 on About and 5.4:1 on Contact.
   -------------------------------------------------------------------------- */

.page-hero::before {
  background: linear-gradient(180deg,
    rgba(7, 33, 52, 0.60) 0%,
    rgba(7, 33, 52, 0.36) 20%,
    rgba(7, 33, 52, 0.76) 42%,
    rgba(7, 33, 52, 0.92) 100%);
}

.page-hero .overline,
.section--media .overline {
  color: #e8d3a0;
  font-size: 0.78rem;
  font-weight: 500;
  text-shadow: 0 1px 12px rgba(7, 33, 52, 0.9);
}
.page-hero--plain .overline {
  color: var(--brass-deep);
  font-size: var(--fs-overline);
  text-shadow: none;
}

/* A gold label near the top of a scrimmed photo band needs a heavier ground
   than the default .section__bg gradient gives it. Scoped to the bands that
   carry one so the other lanes' imagery is untouched. */
.section__bg--deep::after {
  background: linear-gradient(180deg,
    rgba(7, 33, 52, 0.86) 0%,
    rgba(7, 33, 52, 0.70) 58%,
    rgba(10, 48, 80, 0.84) 100%);
}

/* --------------------------------------------------------------------------
   Hero crops (C4, C5). Interior heroes are bottom-aligned letterboxes, so the
   default 50% centre cut Gina's forehead on About and her head off entirely
   on Contact at 1440. Below 768px the box is taller than the scaled image and
   the vertical position stops mattering, so these are desktop-only.
   -------------------------------------------------------------------------- */

@media (min-width: 768px) {
  .page-hero--about .page-hero__media img   { object-position: 50% 24%; }
  .page-hero--contact .page-hero__media img { object-position: 50% 0%; }
}
/* Portrait exterior frame: hold the front porch and the pink door in the band,
   not the lawn and the fence. */
.page-hero--dehaven .page-hero__media img { object-position: 50% 52%; }
/* Project heroes carry a breadcrumb high in the band, where the standard
   gradient is at its lightest, so a blown-out sky or white trim behind it read
   at about 3.7:1. These three get a flatter, deeper scrim of their own. */
.page-hero--project::before {
  background: linear-gradient(180deg,
    rgba(7, 33, 52, 0.72) 0%,
    rgba(7, 33, 52, 0.74) 30%,
    rgba(7, 33, 52, 0.86) 70%,
    rgba(7, 33, 52, 0.94) 100%);
}
.page-hero .crumbs { color: rgba(250, 247, 242, 0.88); }

/* Kitchen frame: the default centre cut sat on the dark window reveal. */
.page-hero--keystone .page-hero__media img { object-position: 50% 72%; }

/* Home hero on a phone (C4). A 16:9 clip inside a full-height portrait box was
   scaled about three times, so barely a quarter of the frame survived and what
   was left read as an out-of-focus close-up. Shortening the band and tightening
   the top padding puts roughly 40 per cent of the frame back on screen. */
@media (max-width: 767px) {
  .hero { min-height: min(62svh, 620px); }
  .hero__inner { padding-top: calc(var(--header-h) + clamp(2rem, 7vh, 4rem)); }
  .hero__media img, .hero__media video { object-position: 50% 42%; }
}

/* --------------------------------------------------------------------------
   Home: Buying / Selling / Designing (C11). Was three identical photo cards.
   Now one tall lead card beside two stacked landscape ones, with the lower of
   the pair indented so the column does not read as a stack of equals. Copy is
   untouched.
   -------------------------------------------------------------------------- */

@media (min-width: 900px) {
  .home-trio {
    grid-template-columns: 7fr 5fr;
    column-gap: clamp(2rem, 4vw, 4rem);
    row-gap: clamp(2.5rem, 4vw, 3.5rem);
    align-items: start;
  }
  .home-trio > :nth-child(1) { grid-column: 1; grid-row: 1 / span 2; }
  .home-trio > :nth-child(2) { grid-column: 2; grid-row: 1; }
  .home-trio > :nth-child(3) {
    grid-column: 2;
    grid-row: 2;
    margin-left: clamp(1.5rem, 3.5vw, 3.5rem);
  }
  .home-trio > :nth-child(1) .editorial-item__media img { aspect-ratio: 5 / 6; }
  .home-trio > :nth-child(2) .editorial-item__media img,
  .home-trio > :nth-child(3) .editorial-item__media img { aspect-ratio: 16 / 11; }
  .home-trio > :nth-child(1) .editorial-item__title { font-size: var(--fs-h2); }
  .home-trio > :nth-child(1) .editorial-item__body {
    font-size: var(--fs-body);
    max-width: 44ch;
  }
}

/* --------------------------------------------------------------------------
   Project galleries (C6). A real 12-column grid: one feature at 8 columns by
   two rows, single frames at 4 columns, an optional full-width closer. The
   4-column frames set the row height, so every row ends on the same x and the
   gutters never change.
   -------------------------------------------------------------------------- */

.project-mosaic {
  display: grid;
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
}
.project-mosaic figure { margin: 0; }
.project-mosaic img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  aspect-ratio: 4 / 3;
}

@media (min-width: 780px) {
  .project-mosaic { grid-template-columns: repeat(12, 1fr); }
  .project-mosaic > figure { grid-column: span 4; }
  .project-mosaic > .project-mosaic__feature {
    grid-column: span 8;
    grid-row: span 2;
  }
  .project-mosaic > .project-mosaic__feature img { aspect-ratio: auto; height: 100%; }
  .project-mosaic > .project-mosaic__full { grid-column: span 12; }
  .project-mosaic > .project-mosaic__full img { aspect-ratio: 24 / 9; }
}

/* Closing CTA band on the project pages: the client's own service lines set
   as a short list rather than an orphan paragraph with an underlined phrase. */
.cta-points {
  list-style: none;
  margin: var(--sp-5) 0 0;
  padding: 0;
  text-align: center;
}
.cta-points li {
  padding: var(--sp-3) 0;
  border-top: 1px solid var(--line-brass);
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.6vw, 1.3rem);
  line-height: 1.5;
  color: rgba(250, 247, 242, 0.92);
}
.cta-points li:last-child { border-bottom: 1px solid var(--line-brass); }

/* --------------------------------------------------------------------------
   Affiliations (C8). The heading is on show instead of visually hidden, and
   the marks are the knocked-out PNGs, sized so the two read as a matched pair
   rather than two rectangles of different aspect.
   -------------------------------------------------------------------------- */

.affiliations__heading {
  margin: 0 0 var(--sp-5);
  font-family: var(--font-sans);
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-overline);
  text-transform: uppercase;
  text-align: center;
  color: var(--brass-deep);
}
.affiliations { gap: clamp(2.5rem, 6vw, 5rem); }
.affiliations img.affiliations__mark {
  filter: none;
  opacity: 0.92;
  width: auto;
}
.affiliations img.affiliations__mark:hover { opacity: 1; }
.affiliations__mark--herron { height: clamp(64px, 6.8vw, 84px); }
.affiliations__mark--houzz { height: clamp(46px, 5vw, 60px); }

/* In the footer the pair is the Herron wordmark and the Houzz tile. Only the
   Houzz tile needs the ivory chip; the Herron lockup is already white. Their
   heights are set against each other so the row reads as one line. */


/* --------------------------------------------------------------------------
   Small things (C10, B14).
   -------------------------------------------------------------------------- */

/* Offset brass frame. `.figure--framed` draws a 55% x 60% box behind the
   photo, which on the Contact portrait showed as a stray 20px corner. This
   one is the full size of the photo, so it reads as a deliberate frame down
   the right and bottom edges. */
.figure--offset { --frame-offset: clamp(0.9rem, 1.6vw, 1.6rem); }
.figure--offset::before {
  content: "";
  position: absolute;
  top: var(--frame-offset);
  left: var(--frame-offset);
  right: calc(var(--frame-offset) * -1);
  bottom: calc(var(--frame-offset) * -1);
  border: 1px solid var(--line-brass);
  z-index: -1;
}

/* Star ratings are an SVG glyph everywhere; the rule is scoped so a stray dingbat would keep its tracking. */
.review__stars:has(svg) {
  display: flex;
  align-items: center;
  gap: 0.22rem;
  letter-spacing: normal;
}
.review__stars svg {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  fill: currentColor;
}

/* ===== Phase 2 lead modal (p2-modal) ===== */

/* The dialog box itself is only the panel; everything around it is ::backdrop,
   so a click that lands on the dialog element is a click on the backdrop. */
.lead-modal {
  width: min(680px, 94vw);
  max-width: none;
  max-height: calc(100vh - 3rem);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  overflow: auto;
  overscroll-behavior: contain;
}
.lead-modal::backdrop { background: rgba(7, 33, 52, 0.92); }
.lead-modal[open] { animation: lead-modal-in 0.36s var(--ease); }
@keyframes lead-modal-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* No <dialog> support: the script toggles this class instead of showModal(). */
dialog:not([open]) { display: none; }
.lead-modal.is-fallback-open {
  position: fixed;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  z-index: 200;
  box-shadow: 0 0 0 100vmax rgba(7, 33, 52, 0.92);
}

.lead-modal__panel {
  position: relative;
  padding: clamp(1.75rem, 4.5vw, 3rem);
  background: var(--shell);
  border: 1px solid var(--line-brass);
  box-shadow: var(--shadow-lift);
}

.lead-modal__title {
  margin: 0.35rem 0 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.85rem, 4.6vw, 2.5rem);
  line-height: 1.12;
  color: var(--navy);
}

.lead-modal__close {
  position: absolute;
  top: 0.45rem; right: 0.45rem;
  width: 44px; height: 44px;
  border: 0;
  background: none;
  color: var(--ink-soft);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
}
.lead-modal__close:hover { color: var(--navy); }
.lead-modal__close:focus-visible { outline: 2px solid var(--aqua-deep); outline-offset: 2px; }

.lead-modal .form { max-width: none; }
.lead-modal .rule { margin-block: var(--sp-4); }

.lead-modal__done { padding-block: var(--sp-2) var(--sp-1); }
.lead-modal__thanks {
  margin: 0 0 var(--sp-5);
  font-size: var(--fs-lede);
  color: var(--ink);
}

/* Both ways to reach her are links now, in every form status line. */
.form__status a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

@media (prefers-reduced-motion: reduce) {
  .lead-modal[open] { animation: none; }
}

/* ==========================================================================
   ===== Phase 2 frames and motion (p2-frames-motion) =====
   ========================================================================== */

/* --------------------------------------------------------------------------
   P1. Frames everywhere.

   Three additions. A negative-side modifier for the offset frame so the brass
   outline can alternate sides down a page; the mat given to the containers
   the lanes built without one (the project mosaics, the blog banner and the
   figures inside a post body); and the two small fixes that let a badge and a
   video button sit inside a .figure without losing their own sizing.
   -------------------------------------------------------------------------- */

/* .figure--frame-left, where the offset outline sits bottom-left instead of
   bottom-right. Used on every other framed figure so a page does not read as
   the same frame four times. Never used on a .split--offset media block: that
   one already bleeds past the left gutter and the outline would follow it off
   the viewport. */
.figure--framed.figure--frame-left::before {
  inset: var(--frame-offset, 0.9rem) var(--frame-offset, 0.9rem)
         calc(-1 * var(--frame-offset, 0.9rem)) calc(-1 * var(--frame-offset, 0.9rem));
}

/* Project mosaics (Parkwood, DeHaven, Keystone Heights) get the same mat the
   .mosaic and .rail items already carry, so the interiors hang in a mount
   instead of butting against each other. Done here rather than as a class on
   each figure because the mosaic markup is one of the generated regions. */
.project-mosaic > figure {
  position: relative;
  background: var(--shell);
  padding: 0.5rem;
  box-shadow: var(--shadow-soft);
}
.project-mosaic > figure::after {
  content: "";
  position: absolute;
  inset: 0.3rem;
  border: 1px solid var(--line);
  pointer-events: none;
}

/* Blog banners and in-body figures. Both are emitted by scripts/build_blog.py,
   so the mat is applied from the stylesheet and survives a rebuild.
   The banner also carries .wrap, whose padding-inline is the page gutter; the
   mat therefore goes on the image box (box-sizing is border-box site-wide) and
   the hairline is a negative outline offset, so the gutter is left alone. */
.post__banner img {
  padding: clamp(0.55rem, 1.1vw, 0.9rem);
  background: var(--paper);
  outline: 1px solid var(--line-brass);
  outline-offset: calc(-1 * clamp(0.3rem, 0.62vw, 0.5rem));
}
.post__body .prose > .figure {
  background: var(--paper);
  padding: clamp(0.55rem, 1.1vw, 0.9rem);
  box-shadow: var(--shadow-soft);
}
.post__body .prose > .figure::after {
  content: "";
  position: absolute;
  inset: clamp(0.24rem, 0.5vw, 0.42rem);
  border: 1px solid var(--line-brass);
  pointer-events: none;
}

/* The affiliation badges now hang in a plate. .figure img would otherwise take
   the height away from the marks, which are sized to a shared cap height. The
   Herron mark is the black wordmark lockup, so its box runs taller than the
   square Houzz tile; the extra height is what puts "Real Estate" on the same
   cap height as the Houzz "2017", which is the pair a reader actually reads. */
.affiliations .figure--plate { display: inline-block; }
.affiliations .figure--plate img.affiliations__mark { width: auto; }
.affiliations .figure--plate img.affiliations__mark--herron { height: clamp(64px, 6.8vw, 84px); }
.affiliations .figure--plate img.affiliations__mark--houzz { height: clamp(46px, 5vw, 60px); }

/* The homepage testimonial button is a portrait of Gina, so it hangs in the
   arch. The radius goes on the button, which already clips, so the scrim and
   the play label follow the arch instead of squaring it off at the top. */
.figure--arch > .video-cta { border-radius: 999px 999px 0 0; }

/* Mats on ink read as ivory chips, not white boxes. .figure--matted already
   does this; .mat (feed and neighborhood tiles) and the mosaics join it. */
.section--ink .mat,
.section--ink .project-mosaic > figure,
.section--media .mat { background: rgba(250, 247, 242, 0.96); }

/* --------------------------------------------------------------------------
   P2. Motion.

   Everything below is opt-in twice over: the stylesheet only speaks inside
   `prefers-reduced-motion: no-preference`, and nothing moves until js/motion.js
   marks the element. motion.js itself returns immediately when reduced motion
   is preferred, so with the setting on there is no attribute to match.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {

  /* 1. Matted interiors drift. A 22s breath, alternating, so a room is never
     caught mid-jump. The container clips, so nothing escapes the mount, and
     the observer pauses the frame the moment it leaves the viewport. */
  @keyframes p2-mat-drift {
    from { transform: scale(1); }
    to   { transform: scale(1.035); }
  }
  [data-drift] { overflow: hidden; }
  [data-drift] > img,
  [data-drift] > a > img {
    animation: p2-mat-drift 22s ease-in-out infinite alternate;
  }
  [data-drift][data-offscreen] > img,
  [data-drift][data-offscreen] > a > img { animation-play-state: paused; }

  /* The editorial cards already scale on hover, and an animation outranks a
     transition on the same property. Drop the drift while the card is under
     the cursor so the existing hover keeps working. */
  .editorial-item:hover > [data-drift] > img,
  .editorial-item:focus-within > [data-drift] > img,
  .editorial-item:hover > [data-drift] > a > img,
  .editorial-item:focus-within > [data-drift] > a > img { animation: none; }

  /* 2. Brass rules draw on from the left. motion.js tags the rules it will
     observe, so a rule is only ever hidden when the script is running. */
  .rule[data-draw] {
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 0.9s var(--ease);
  }
  .rule[data-draw].is-drawn { transform: scaleX(1); }

  /* 3 and 4. The offset frame settles into place on reveal, then drifts a few
     pixels with the scroll. Settle rides `transform` so it can transition;
     parallax rides the independent `translate` property so the per-frame
     writes are not smoothed into lag. */
  .js .figure--framed { --settle-x: -6px; --settle-y: -6px; }
  .js .figure--framed.figure--frame-left { --settle-x: 6px; }
  .js .figure--framed.is-revealed,
  .js .is-revealed .figure--framed { --settle-x: 0px; --settle-y: 0px; }

  .figure--framed::before {
    transform: translate(var(--settle-x, 0px), var(--settle-y, 0px));
    transition: transform 0.9s var(--ease);
    translate: 0 var(--parallax, 0px);
  }
}

/* ===== Phase 2 fix pass (post-merge) ===== */

:root { --brass-light: #e8d3a0; --ink-soft-aa: #4f6579; }

/* Rails: items of different heights sit on a common top edge instead of
   stretching their mats to the tallest one. */
.rail__track { align-items: flex-start; }

/* Stars over photography need the lighter brass to clear 4.5:1. */
.section--media .review__stars { color: var(--brass-light); }

/* A review wall over a busy photograph gets a deeper scrim on wide screens,
   where the copy runs across blinds and pillows at full size. */
@media (min-width: 1000px) {
  .section--media.section--reviews .section__bg::after,
  .section--media:has(.reviews) .section__bg::after {
    background: linear-gradient(180deg, rgba(7,33,52,0.86) 0%, rgba(7,33,52,0.8) 55%, rgba(10,48,80,0.88) 100%);
  }
}

/* Rate rows without a price are a plain list, not a priced row with a hole. */
.rate-row--plain,
.rate-row:not(:has(.rate-row__price)) {
  grid-template-columns: minmax(0, 1fr);
  padding-block: 0.55rem;
  border-top-color: var(--line);
}

/* Offset frames at phone width: a smaller offset and a matching margin so the
   outline never lands a few pixels from the viewport edge. */
@media (max-width: 640px) {
  .figure--framed, .figure--offset, .figure--frame-left { --frame-offset: 0.55rem; }
  .figure--framed:not(.figure--frame-left) { margin-right: 0.55rem; }
  .figure--frame-left { margin-left: 0.55rem; }
}

/* Captions clear 4.5:1 on ivory. */
.figure__caption { color: var(--ink-soft-aa); }
/* ==========================================================================
   ===== Phase 2 chrome (p2-chrome) =====
   P3 navigation and P4 transparent header. Appended by the chrome lane;
   nothing above this line was touched.
   ========================================================================== */

/* The header is fixed on every photo-hero page now, so an in-page anchor that
   used to land flush at the top would land underneath it. */
html { scroll-padding-top: calc(var(--header-h) + 1rem); }

/* --------------------------------------------------------------------------
   P4. Two marks, one box. The transparent state needs the light mark and the
   solid state the dark one. Both images ship on every page and share a single
   grid cell, so the swap is a visibility toggle: no second request at the
   moment of swapping, no src rewrite, and no reflow. The two files are one
   drawing in two colourways, so the box never changes size either.
   -------------------------------------------------------------------------- */
.header__logo { display: grid; }
.header__mark { grid-area: 1 / 1; transition: opacity var(--dur) var(--ease); }
.header__mark--light { opacity: 0; }
.js .site-header--overlay:not(.is-stuck) .header__mark--dark { opacity: 0; }
.js .site-header--overlay:not(.is-stuck) .header__mark--light { opacity: 1; }

/* --------------------------------------------------------------------------
   Round 5, widened in round 6. Each mark is the Gina and Herron lockup, so the
   brokerage stands beside her name in the header of every page at every width.
   The dark and light pair above is untouched, and the swap is still nothing but
   an opacity change, which is only true because the two lockup files are one
   drawing in two colourways rather than two files. They have to be: Herron
   supplies a black-type and a white-type artwork that set the same wordmark at
   the same size but draw the heron about 15% taller in the white one, and
   crossfading those would resize a brokerage mark on every scroll.
   scripts/make_lockups.py cuts both halves of both files from one geometry and
   takes the type to white for the dark ground, so the two outputs share an
   alpha channel and nothing moves.

   Round 5 kept her own logo below 1080, on the Combo Logos note that a
   complete horizontal lockup does not belong in a phone bar. That note is
   about legibility; the adjacency rule is about her licence, and it wins. So
   the width at each breakpoint is set from the part of the lockup that is
   hers: her half is the first 62.5% of the drawing, so 368px holds her script
   at the 230px it read at from 641 to 1079, and 360px and 300px hold it where
   round 5 put it above 1080.

   Below 641 the arithmetic does not close. Her script read at 180px there, and
   holding that would want a 288px lockup, which with the 44px hamburger and
   the 20px gutters does not fit a 375px bar. 272px is the widest declared
   width that behaves, and the flex row shrinks it to 267.5px at 375, which
   reads her script at 167px, seven per cent down. The bar itself is unchanged
   at 72px: the lockup is 52.5px in it, against 71px in the 88px bar above
   1080, so the phone bar is the airier of the two.
   -------------------------------------------------------------------------- */
@media (min-width: 1080px) {
  .header__mark { width: 360px; }
}

/* --------------------------------------------------------------------------
   P3. Nine flat items overflowed at 1280. Six slots and a button: Home,
   About Me, Buy and Sell, Design, Journal, Contact Me.

   Each list item is the full height of the header bar so a panel anchored at
   top:100% opens flush against the bottom edge of the header, with no dead
   gap for the pointer to fall through on its way down. The underline still
   sits under the text, because .nav__link is its own positioning context.
   -------------------------------------------------------------------------- */
@media (min-width: 1080px) {
  .nav { display: flex; align-self: stretch; }
}
.nav__list {
  height: 100%;
  align-items: stretch;
  gap: clamp(0.9rem, 1.5vw, 1.6rem);
}
.nav__item { position: relative; display: flex; align-items: center; }

.nav__parent {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  border: 0;
  background: none;
  cursor: pointer;
}
/* Not an arrow: two hairlines rotated into a caret, per the studio rule. */
.nav__caret {
  width: 6px;
  height: 6px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  opacity: 0.7;
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--dur) var(--ease);
}
.nav__item--group.is-open .nav__caret { transform: translateY(1px) rotate(225deg); }

.nav__panel {
  position: absolute;
  top: 100%;
  left: 50%;
  z-index: 5;
  min-width: max(12rem, 100%);
  margin: 0;
  padding: 0.6rem 0;
  list-style: none;
  background: var(--shell);
  border: 1px solid var(--line-brass);
  box-shadow: 0 26px 50px -34px rgba(7, 33, 52, 0.55);
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -0.5rem);
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), visibility 0.22s;
}
.nav__item--group.is-open .nav__panel {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}
.nav__panel-link {
  display: block;
  padding: 0.5rem 1.5rem;
  font-family: var(--font-sans);
  font-size: var(--fs-overline);
  font-weight: 400;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink);
  transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.nav__panel-link:hover,
.nav__panel-link:focus-visible {
  color: var(--brass-deep);
  background: var(--shell-warm);
}
.nav__panel-link[aria-current="page"] {
  color: var(--brass-deep);
  box-shadow: inset 2px 0 0 var(--brass);
}

/* The group holding the current page carries the same brass as a current link. */
.nav__parent[aria-current="true"] { color: var(--brass-deep); }
.nav__parent[aria-current="true"]::after { transform: scaleX(1); }
.js .site-header--overlay:not(.is-stuck) .nav__parent[aria-current="true"] { color: var(--brass-soft); }

/* The CTA. Kept as a link to /contact so it still works without script. */
.nav__cta { padding: 0.72rem 1.4rem; white-space: nowrap; }
.js .site-header--overlay:not(.is-stuck) .nav__cta {
  border-color: rgba(250, 247, 242, 0.7);
  color: var(--shell);
}
.js .site-header--overlay:not(.is-stuck) .nav__cta:hover,
.js .site-header--overlay:not(.is-stuck) .nav__cta:focus-visible {
  background: var(--shell);
  color: var(--navy);
  border-color: var(--shell);
}

/* 1080 to 1279 is the tight end: shorten the mark and the button so the row
   still clears the gutter at 1180. The lockup steps down in the same ratio as
   her logo did, so her script stays the same size across the breakpoint and
   only the Herron half gives ground. */
@media (min-width: 1080px) and (max-width: 1279px) {
  .header__logo .header__mark { width: 300px; }
  .nav__cta { padding: 0.68rem 1.05rem; }
}

/* --------------------------------------------------------------------------
   P3 on a phone. The overlay carries the same six slots as headed sections.
   Thirteen links do not fit at the old display size on a 667px-tall screen,
   so the loose links keep the large Cormorant and the grouped ones step down
   under a brass letterspaced heading. margin-block: auto centres the block
   when there is room and lets it scroll from the top when there is not;
   justify-content: center clips the first item instead.
   -------------------------------------------------------------------------- */
.nav-overlay {
  justify-content: flex-start;
  padding-block: calc(var(--header-h) + 1rem) 2rem;
}
.nav-overlay > nav { width: 100%; margin-block: auto; }
.nav-overlay__list li + li { margin-top: 0.2rem; }
.nav-overlay__link { font-size: clamp(1.5rem, 5.6vw, 2.1rem); }

.nav-overlay__group { margin-top: var(--sp-4); }
.nav-overlay__heading {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin-bottom: 0.4rem;
  font-family: var(--font-sans);
  font-size: var(--fs-overline);
  font-weight: 500;
  letter-spacing: var(--track-overline);
  text-transform: uppercase;
  color: var(--brass-soft);
}
.nav-overlay__heading::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--line-brass);
}
.nav-overlay__sublist { list-style: none; }
.nav-overlay__link--sub { font-size: clamp(1.2rem, 4.4vw, 1.6rem); }
.nav-overlay__link--cta {
  margin-top: var(--sp-5);
  padding-bottom: 0.45rem;
  border-bottom: 1px solid var(--brass);
}

/* --------------------------------------------------------------------------
   P4. Interior photo heroes start at the top of the viewport now, behind the
   fixed transparent header. The band is taller so the header sits on
   photograph rather than on the first line of type, and the inner block
   carries the header height in its top padding so a long title cannot slide
   underneath it.
   -------------------------------------------------------------------------- */
.page-hero--overlay { min-height: clamp(440px, 64vh, 680px); }
.page-hero--overlay .page-hero__inner {
  padding-top: calc(var(--header-h) + clamp(3rem, 8vh, 5.5rem));
  padding-bottom: clamp(3rem, 8vh, 5.5rem);
}

/* The scrim carries the header text as well as the title block now, so it
   opens deeper than the B14 ramp and holds that through the header band
   before it lightens over the middle of the photograph. Against a blown-out
   white frame the worst case at the bottom edge of the header is 4.9:1 for
   ivory type; sampled on about, contact, social and around-town at 1440 and
   375. Project heroes with a breadcrumb high in the band are included. */
.page-hero--overlay::before {
  background: linear-gradient(180deg,
    rgba(7, 33, 52, 0.80) 0%,
    rgba(7, 33, 52, 0.66) 14%,
    rgba(7, 33, 52, 0.42) 30%,
    rgba(7, 33, 52, 0.78) 56%,
    rgba(7, 33, 52, 0.93) 100%);
}

/* The marker the sticky-header observer watches. A 1px dot sitting at y=0 had
   already left the viewport before anything was scrolled, so the header
   rendered solid from the first paint and the transparent state was never
   seen. Two header heights of band gives the bar a stretch of hero to be
   transparent over and puts the swap at about 176px of scroll on a desktop,
   144px on a phone. */
.header-sentinel { height: calc(var(--header-h) * 2); }

/* --------------------------------------------------------------------------
   The transparent bar carries its own ground. Left to each hero's own scrim,
   the header type was only as legible as whatever happened to be behind it:
   the home hero has a bright band at the top right where its side gradient has
   already run out, and ivory nav type measured 4.4:1 against the first frame
   of the video there. This gradient lives inside the header, is the only thing
   it paints in the transparent state, and fades out below the bar so it reads
   as part of the photograph rather than as a panel. It leaves with the
   transparent state when the solid one takes over.

   Sampled off the rendered pixels behind the logo, every nav label, the CTA
   and the hamburger, on all twelve photo-hero pages at 1440, 1280, 1180 and
   375, and across eleven frames of both ambient videos: worst case 5.87:1.
   -------------------------------------------------------------------------- */
.js .site-header--overlay::before {
  content: "";
  position: absolute;
  inset: 0 0 -2.5rem 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(7, 33, 52, 0.44) 0%,
    rgba(7, 33, 52, 0.28) 58%,
    rgba(7, 33, 52, 0) 100%);
  transition: opacity var(--dur) var(--ease);
}
.site-header--overlay.is-stuck::before { opacity: 0; }

/* Brass on a photograph is the B14 problem again: brass-soft behind the nav
   measured between 2.7:1 and 3.7:1 across the hero pages. In the transparent
   state the current page keeps ivory type and is marked by its rule instead,
   which goes ivory to match. The solid state keeps the brass it always had. */
.js .site-header--overlay:not(.is-stuck) .nav__link[aria-current="page"],
.js .site-header--overlay:not(.is-stuck) .nav__parent[aria-current="true"] { color: var(--shell); }
.js .site-header--overlay:not(.is-stuck) .nav__link::after { background: var(--shell); }

/* Bleed splits below 1300px: the photo runs to the viewport edge, so the offset
   frame is thrown toward that edge. Only its bottom rule stays visible, and the
   vertical rule that used to crowd the copy is gone. */
@media (max-width: 1300px) {
  .split--offset:not(.split--reverse) .split__media .figure--framed::before {
    inset: var(--frame-offset, 0.9rem) var(--frame-offset, 0.9rem)
           calc(-1 * var(--frame-offset, 0.9rem)) calc(-1 * var(--frame-offset, 0.9rem));
  }
}

/* ==========================================================================
   RELOCATION GUIDE (2026-09-18)
   The guide's own page, plus the invitation band that carries its cover on
   Buying and Around Town.
   ========================================================================== */

/* The contents of the guide, set as an editorial list: chapter names only,
   brass hairlines between them, two columns once there is room for two.
   No numbers and no icons, per the studio rules. */
.chapter-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-bottom: 1px solid var(--line-brass);
}
@media (min-width: 760px) {
  .chapter-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: repeat(6, auto);
    grid-auto-flow: column;
    column-gap: clamp(2rem, 6vw, 5rem);
  }
}
.chapter-list__item {
  border-top: 1px solid var(--line-brass);
  padding: clamp(0.7rem, 1.6vw, 1.05rem) 0;
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 1.5vw, 1.35rem);
  font-weight: 500;
  line-height: 1.3;
  color: var(--navy);
}

/* The cover is a portrait page scan, so it is held to a width that reads as a
   book on the desk rather than a poster. */
.guide-cover { max-width: 360px; }

/* The download link ships in the page, hidden, and site.js reveals it when the
   request on this page succeeds. The attribute alone would lose to .btn-row's
   own display, so say it here. */
.guide-link[hidden] { display: none; }

.guide-fallback {
  margin-top: var(--sp-4);
  max-width: 52ch;
  font-size: var(--fs-small);
  line-height: 1.7;
  color: var(--ink-soft);
}

/* The invitation band on Buying and Around Town: the cover in its mat, her own
   heading from page three of the guide, and the line with its button. Two
   columns from 720, with the cover beside both text rows; three from 1100, so
   a wide screen has no dead half to the right of one line. */
.guide-band {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
}
@media (min-width: 720px) {
  .guide-band {
    grid-template-columns: minmax(0, 200px) minmax(0, 1fr);
    row-gap: var(--sp-3);
  }
  .guide-band__cover { grid-row: span 2; }
}
@media (min-width: 1100px) {
  .guide-band { grid-template-columns: minmax(0, 200px) minmax(0, 6fr) minmax(0, 5fr); }
  .guide-band__cover { grid-row: auto; }
}
.guide-band__cover { width: 100%; max-width: 200px; }
.guide-band .btn-row { margin-top: var(--sp-4); }

/* ==========================================================================
   COMPLIANCE BLOCK (2026-09-18)
   The brokerage line that sits above every form, the phone-consent checkbox
   above the submit button, the privacy link beside it, and the source line
   under a set of reviews. Appended, so these win over section 12.
   ========================================================================== */

/* The broker line is the form's note style at the top of the form, so the
   name of the brokerage is the first thing read above any point of contact. */
.form__note--broker { margin-bottom: var(--sp-2); }

/* Consent (F.S. 501.059). The box is unchecked and stays optional; the note
   under it is the disclosure, set a step smaller than the note above. */
.consent { margin-top: var(--sp-5); }
.consent__check {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--ink);
  cursor: pointer;
}
.consent__check input {
  flex: 0 0 auto;
  width: 1rem;
  height: 1rem;
  margin: 0.2rem 0 0;
  accent-color: var(--aqua-deep);
}
.consent__check input:focus-visible {
  outline: 2px solid var(--aqua-deep);
  outline-offset: 3px;
}
/* The email-list box sits under the SMS disclosure in the same block, so it
   needs the gap the disclosure does not. Adjacent sibling rather than a
   modifier class, so the box standing alone on a form with no phone field
   (the relocation guide's) takes no stray margin. */
.consent__note + .consent__check { margin-top: var(--sp-3); }
.consent__note {
  margin-top: 0.55rem;
  font-size: 0.78rem;
  line-height: 1.6;
  /* The disclosure is small and legally load-bearing, so it takes the darker
     of the two soft inks and clears AA at this size. */
  color: var(--ink-soft-aa);
}
.section--ink .consent__check,
.section--media .consent__check { color: rgba(250, 247, 242, 0.85); }
.section--ink .consent__check input,
.section--media .consent__check input { accent-color: var(--aqua); }
.section--ink .consent__note,
.section--media .consent__note { color: rgba(250, 247, 242, 0.68); }
/* The privacy link rides in the actions row beside the submit button. */
.form__privacy {
  font-size: var(--fs-small);
  color: var(--ink-soft);
  border-bottom: 1px solid var(--line-brass);
  padding-bottom: 1px;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.form__privacy:hover, .form__privacy:focus-visible {
  border-bottom-color: var(--brass);
  color: var(--brass-deep);
}
.section--ink .form__privacy,
.section--media .form__privacy { color: rgba(250, 247, 242, 0.75); }
.section--ink .form__privacy:hover,
.section--media .form__privacy:hover { color: var(--brass-soft); }

/* The rates carry their own date under the whole grid, not inside a column. */
.rates__footnote {
  margin: clamp(2rem, 4vw, 3rem) 0 0;
  font-size: var(--fs-small);
  color: var(--ink-soft);
}
.section--ink .rates__footnote { color: rgba(250, 247, 242, 0.7); }

/* Under a reviews block: where the words came from, in the quiet caption size. */
.reviews__source {
  margin-top: var(--sp-5);
  font-size: var(--fs-small);
  color: var(--ink-soft-aa);
}
.section--ink .reviews__source,
.section--media .reviews__source { color: rgba(250, 247, 242, 0.7); }
