/* =========================================================================
   Erica Urenda — San Gabriel Valley real estate.
   The whole design system. Hand-written, no build step.

   Brand values come from PART 1 of Brett's build spec, which pulled them from
   The Rockwell Group, the site the client named as the aesthetic reference.

   Every rule tagged [CHECKLIST n.n] is an acceptance criterion from PART 2 of
   that spec. Each one is a defect a previous Appomark build shipped. Do not
   "simplify" them away.
   ========================================================================= */

/* [CHECKLIST 2.3] FIRST rule in the sheet, deliberately. Without it iOS Safari
   paints button text in system blue while desktop renders black, so the bug is
   invisible in desktop testing. */
button {
  color: inherit;
  font: inherit;
}

/* ------------------------------------------------------------------ tokens */
:root {
  --paper: #FFFFFF;             /* pure white */
  --cream: #FBF9F7;             /* page background, warm off white */
  --sand: #ECE7E1;              /* warm beige, alternating sections */
  --line: #DDDDDD;              /* hairline rules and borders */
  --ink: #000000;               /* body and heading text on light */
  --ink-soft: rgba(0, 0, 0, .66);
  --ink-faint: rgba(0, 0, 0, .42);
  --dark: #34394D;              /* deep slate, ONE contrast band only */

  /* [CHECKLIST 2.4] Neutral near black RGB triplet for photo overlays. NEVER a
     brand colour: a tinted scrim colours every photograph on the site and costs
     a full revision round to trace back. */
  --scrim: 10, 9, 8;

  --display: 'Noto Serif Display', 'Times New Roman', serif;
  --body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;

  --nav-h: 92px;
  --wrap: 1240px;
  --ease: cubic-bezier(.22, .61, .36, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--body);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.65;
  /* [CHECKLIST 2.5] Belt and braces against sideways scroll on a phone. */
  overflow-x: hidden;
}

/* `img { height: auto }` is load-bearing. Every <img> carries width/height
   attributes to reserve its box against layout shift. Without this the
   attribute becomes the used height and a 2400x1800 photo in a 580px column
   renders 580x1800, badly stretched. */
img {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: inherit;
}

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 300;
}

p {
  margin: 0;
}

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

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--ink);
  color: var(--paper);
  padding: 12px 18px;
  font-size: 13px;
}

.skip-link:focus {
  left: 12px;
  top: 12px;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 40px;
}

@media (max-width: 860px) {
  .wrap { padding: 0 24px; }
}

@media (max-width: 560px) {
  .wrap { padding: 0 20px; }
}

/* ---------------------------------------------------------------- type kit */
/* Display face: Noto Serif Display 300, uppercase, wide letterspacing. */
.display {
  font-family: var(--display);
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: .05em;
  line-height: 1.14;
  color: var(--ink);
}

.d1 { font-size: clamp(32px, 5vw, 48px); }
.d2 { font-size: clamp(26px, 3.6vw, 36px); }
.d3 { font-size: clamp(20px, 2.4vw, 26px); }

/* Eyebrows and nav share the small uppercase Inter setting. */
.eyebrow {
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 1.4px;
  color: var(--ink-soft);
  margin-bottom: 16px;
}

/* [CHECKLIST 1.2 note] Body paragraphs are SENTENCE CASE at 16px. The reference
   site sets some body copy uppercase at 12px; that is not copied here, it hurts
   readability on a consumer site. */
.lede {
  font-size: clamp(16px, 1.5vw, 18px);
  line-height: 1.7;
  color: var(--ink-soft);
  max-width: 62ch;
}

.prose p + p { margin-top: 18px; }

.prose {
  color: var(--ink-soft);
  max-width: 68ch;
}

.measure { max-width: 68ch; }

/* ----------------------------------------------------------------- buttons */
.btn {
  /* [CHECKLIST 2.1] inline-flex + nowrap, so a button never wraps to two lines
     however tight its column gets. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  gap: 10px;
  padding: 15px 30px;
  border: 1px solid var(--ink);
  border-radius: 0;
  background: none;
  font-family: var(--body);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .35s var(--ease), color .35s var(--ease),
              border-color .35s var(--ease), opacity .2s linear;
}

.btn-primary {
  background: var(--ink);
  color: var(--paper);
}

.btn-primary:hover {
  background: transparent;
  color: var(--ink);
}

.btn-ghost {
  background: transparent;
  color: var(--ink);
}

.btn-ghost:hover {
  background: var(--ink);
  color: var(--paper);
}

/* On a photograph the outline has to be white to be seen at all. */
.btn-on-photo {
  border-color: rgba(255, 255, 255, .85);
  color: #fff;
}

.btn-on-photo:hover {
  background: #fff;
  color: var(--ink);
}

.btn[disabled] {
  opacity: .4;
  cursor: not-allowed;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 32px;
}

/* A quiet text link with a rule under it, used for "more about" style links. */
.link-more {
  display: inline-block;
  margin-top: 26px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--ink);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  text-decoration: none;
  transition: opacity .25s linear;
}

.link-more:hover { opacity: .6; }

/* -------------------------------------------------------------- navigation */
/* [CHECKLIST 2.1] Flex, never `1fr auto 1fr` with no gap: that collapses the
   bar into a squeezed cluster the moment the link set grows. */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  background: transparent;
  border-bottom: 1px solid transparent;
  /* Background only. No shrink, no hide on scroll, no blur. */
  transition: background-color .35s var(--ease), border-color .35s var(--ease);
}

.nav-inner {
  display: flex;
  align-items: center;
  gap: 32px;
  width: 100%;
  max-width: var(--wrap);
  min-height: var(--nav-h);
  margin: 0 auto;
  padding: 0 40px;
}

/* [CHECKLIST 2.1] Solid cream with a hairline once scrolled past the hero. */
.nav.is-solid {
  background: var(--cream);
  border-bottom-color: var(--line);
}

/* [CHECKLIST 2.2] While the mobile menu is open the bar keeps a solid
   background whatever the scroll position, or the close X sits on a
   transparent bar over a light panel and disappears. */
body.menu-open .nav {
  background: var(--cream);
  border-bottom-color: var(--line);
}

/* The wordmark IS the brand: there is no logo file. Built as markup with one
   class so swapping in a real logo later is a single change. */
.wordmark {
  display: block;
  text-decoration: none;
  color: var(--ink);
  line-height: 1;
}

.wordmark-name {
  display: block;
  font-family: var(--display);
  font-weight: 300;
  font-size: 20px;
  letter-spacing: .18em;
  text-transform: uppercase;
  white-space: nowrap;
}

.wordmark-sub {
  display: block;
  margin-top: 5px;
  font-family: var(--body);
  font-size: 9px;
  font-weight: 400;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* Over the hero photograph, before the bar goes solid.

   [CHECKLIST 2.2] The `body:not(.menu-open)` guard is load-bearing, not tidiness.
   Opening the mobile menu at the TOP of the page makes the bar solid cream while
   the nav still has no `.is-solid` class, so without this guard the wordmark and
   the burger stayed white and vanished into the bar. It is the same defect the
   checklist calls out for the close X, one element over. */
body:not(.menu-open) .nav:not(.is-solid) .wordmark { color: #fff; }
body:not(.menu-open) .nav:not(.is-solid) .wordmark-sub { color: rgba(255, 255, 255, .8); }
body:not(.menu-open) .nav:not(.is-solid) .nav-link { color: #fff; }
body:not(.menu-open) .nav:not(.is-solid) .nav-link::after { background: #fff; }
body:not(.menu-open) .nav:not(.is-solid) .nav-cta .btn { border-color: rgba(255, 255, 255, .85); color: #fff; }
body:not(.menu-open) .nav:not(.is-solid) .nav-cta .btn:hover { background: #fff; color: var(--ink); }
body:not(.menu-open) .nav:not(.is-solid) .nav-burger { color: #fff; }

/* A page with no hero photograph behind the bar starts solid, so the bar is
   never white text on a cream page. Set on <body> per page. */
body.nav-solid .nav {
  background: var(--cream);
  border-bottom-color: var(--line);
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 28px;
  margin-left: auto;
}

.nav-link {
  position: relative;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  padding: 6px 0;
}

.nav-link::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 0;
  height: 1px;
  background: var(--ink);
  transition: width .3s var(--ease);
}

.nav-link:hover::after,
.nav-link.is-current::after { width: 100%; }

.nav-cta { margin-left: 8px; }

.nav-cta .btn {
  padding: 13px 22px;
  font-size: 11px;
}

.nav-burger {
  display: none;
  margin-left: auto;
  padding: 8px;
  border: 0;
  background: none;
  color: var(--ink);
  cursor: pointer;
}

/* [CHECKLIST 2.1] Switch to the mobile menu at 1150px, not 1024px. Between
   those two widths the six links plus the CTA do not fit the bar. */
@media (max-width: 1150px) {
  .nav-links,
  .nav-cta { display: none; }
  .nav-burger { display: block; }
  .nav-inner { padding: 0 24px; }
}

@media (max-width: 560px) {
  :root { --nav-h: 78px; }
  .nav-inner { padding: 0 20px; }
  .wordmark-name { font-size: 17px; letter-spacing: .14em; }
  .wordmark-sub { font-size: 8px; letter-spacing: .2em; }
}

/* ------------------------------------------------------------ mobile panel */
/* [CHECKLIST 2.2] No Home item: the wordmark is the home link. No scrolling,
   shrinking or zoom animations inside the panel. */
.mobile-panel {
  position: fixed;
  inset: 0;
  z-index: 99;
  display: none;
  flex-direction: column;
  gap: 6px;
  background: var(--cream);
  /* [CHECKLIST 2.2] Reserve the fixed bar's height so no item can sit behind
     it on a 667px tall phone. */
  padding: calc(var(--nav-h) + 40px) 28px 40px;
  overflow-y: auto;
}

.mobile-panel.is-open { display: flex; }

.mobile-panel a {
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
  font-family: var(--display);
  font-size: 22px;
  font-weight: 300;
  letter-spacing: .05em;
  text-transform: uppercase;
  text-decoration: none;
}

.mobile-panel .btn {
  margin-top: 26px;
  align-self: flex-start;
  border-bottom-width: 1px;
}

/* [CHECKLIST 2.2] The burger swaps to a close X while the panel is open, and
   the guard above keeps it dark against the light panel. */
.nav-burger .i-close { display: none; }
body.menu-open .nav-burger .i-open { display: none; }
body.menu-open .nav-burger .i-close { display: block; }

/* ------------------------------------------------------------------- hero */
.hero {
  position: relative;
  display: flex;
  align-items: center;
  /* [CHECKLIST 2.4] 100dvh, NOT 100svh. svh leaves the next section bleeding
     in under the collapsed browser chrome on a phone. */
  min-height: 100dvh;
  padding: calc(var(--nav-h) + 40px) 0 96px;
  overflow: hidden;
}

.hero-media {
  position: absolute;
  inset: 0;
}

.hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* [CHECKLIST 2.4] The site is light, so the scrim stays light: roughly .30 to
   .45, only as strong as the text needs. The middle stop sat at .22 in the
   first build and the sub-line disappeared into the sunlit wall of the hero
   photograph, so it is back inside the specified range. */
.hero-media::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom,
      rgba(var(--scrim), .40) 0%,
      rgba(var(--scrim), .34) 45%,
      rgba(var(--scrim), .46) 100%);
}

.hero .wrap {
  position: relative;
  z-index: 1;
  text-align: center;
}

/* The hero name treatment: the same wordmark at display scale, spanning the
   hero. This is what makes a name work as a brand without a logo. */
.hero-name {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(40px, 7vw, 96px);
  letter-spacing: .12em;
  line-height: 1.05;
  text-transform: uppercase;
  color: #fff;
  margin: 0;
}

.hero-sub {
  margin-top: 22px;
  font-size: clamp(10px, 1.2vw, 13px);
  font-weight: 400;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .9);
}

.hero .btn-row { justify-content: center; margin-top: 44px; }

/* [CHECKLIST 2.4] Any scroll cue hides at 860px. */
.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 34px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  z-index: 1;
  font-size: 10px;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .85);
}

.scroll-cue .line {
  width: 1px;
  height: 46px;
  background: linear-gradient(to bottom, rgba(255, 255, 255, .9), rgba(255, 255, 255, 0));
}

@media (max-width: 860px) {
  .scroll-cue { display: none; }
}

/* ------------------------------------------------------------ page headers */
/* [CHECKLIST 2.4] 44svh with padding-top just clearing the nav and modest
   bottom padding. Never 60vh with flex-end plus 120px top padding: that leaves
   a dead band above the heading on a phone. */
.page-header {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 44svh;
  padding-top: 104px;
  padding-bottom: 52px;
  overflow: hidden;
}

.page-header .hero-media::after {
  background: linear-gradient(to bottom,
    rgba(var(--scrim), .34) 0%,
    rgba(var(--scrim), .26) 50%,
    rgba(var(--scrim), .44) 100%);
}

.page-header .wrap {
  position: relative;
  z-index: 1;
}

.page-header .eyebrow { color: rgba(255, 255, 255, .82); }

.page-header .display { color: #fff; }

.page-header .lede {
  color: rgba(255, 255, 255, .92);
  margin-top: 18px;
}

@media (max-width: 560px) {
  .page-header { padding-top: 96px; padding-bottom: 40px; }
}

/* ---------------------------------------------------------------- sections */
.section {
  padding: 104px 0;
}

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

.section-cream { background: var(--cream); }
.section-paper { background: var(--paper); }
.section-sand { background: var(--sand); }

/* [CHECKLIST 1.1] --dark is used sparingly: the Neighborhoods band on the
   homepage and nothing else. The site is light. Its power comes from
   restraint, not from adding dark sections. */
.section-dark {
  background: var(--dark);
  color: #fff;
}

.section-dark .display,
.section-dark .section-head .display { color: #fff; }

.section-dark .eyebrow,
.section-dark .lede { color: rgba(255, 255, 255, .78); }

@media (max-width: 860px) {
  .section { padding: 72px 0; }
  .section-tight { padding: 56px 0; }
}

.section-head {
  max-width: 720px;
  margin-bottom: 48px;
}

.section-head.is-centred {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.section-head .lede { margin-top: 18px; }

.section-head.is-centred .lede { margin-left: auto; margin-right: auto; }

.rule {
  height: 1px;
  background: var(--line);
  border: 0;
  margin: 0;
}

/* ------------------------------------------------------------ intro strip */
.intro-strip {
  padding: 92px 0;
  text-align: center;
}

.intro-strip p {
  max-width: 40ch;
  margin: 0 auto;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(20px, 2.4vw, 28px);
  line-height: 1.5;
  letter-spacing: .01em;
}

/* ----------------------------------------------------------- numbers band */
.stats {
  display: grid;
  gap: 40px;
  grid-template-columns: repeat(4, 1fr);
  padding: 100px 0;
}

.stats-3 { grid-template-columns: repeat(3, 1fr); }

.stat {
  position: relative;
  text-align: center;
  /* [CHECKLIST 2.5] A grid cell must be allowed to shrink. */
  min-width: 0;
}

/* Thin vertical hairlines between stats on desktop, hidden on mobile. */
.stat + .stat::before {
  content: '';
  position: absolute;
  left: -20px;
  top: 8%;
  bottom: 8%;
  width: 1px;
  background: var(--line);
}

.stat-value {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(40px, 5.5vw, 76px);
  line-height: 1;
  color: var(--ink);
}

.stat-label {
  margin-top: 14px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--ink-soft);
}

@media (max-width: 860px) {
  .stats,
  .stats-3 {
    grid-template-columns: repeat(2, 1fr);
    gap: 44px 24px;
    padding: 64px 0;
  }
  .stat + .stat::before { display: none; }
}

@media (max-width: 460px) {
  .stats,
  .stats-3 { grid-template-columns: 1fr; }
}

/* ----------------------------------------------------- split image + text */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 72px;
}

.split-body { min-width: 0; }

.split-media { min-width: 0; }

.split-media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

/* [CHECKLIST 2.6] No z-index:-1 decorative frames anywhere. They break inside
   any ancestor with a transform, and the reveal animation creates one. */

@media (max-width: 1024px) {
  .split { gap: 44px; }
}

/* [CHECKLIST 2.6] On mobile, text ALWAYS stacks above its photo. Set order
   explicitly on both children, including in reversed splits: DOM order puts
   the photo first there, and relying on the default would leave two photos
   touching where two splits meet. */
@media (max-width: 860px) {
  .split {
    grid-template-columns: 1fr;
    gap: 32px;
  }
  .split .split-body { order: 1; }
  .split .split-media { order: 2; }
}

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

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

@media (max-width: 640px) {
  .listing-grid { grid-template-columns: 1fr; }
}

.listing-card {
  display: block;
  min-width: 0;
  background: var(--paper);
  border: 1px solid var(--line);
  text-decoration: none;
  color: var(--ink);
  transition: border-color .35s var(--ease);
}

.listing-card:hover { border-color: var(--ink); }

.listing-media {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--sand);
  overflow: hidden;
}

.listing-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .6s var(--ease);
}

.listing-card:hover .listing-media img { transform: scale(1.04); }

.listing-status {
  position: absolute;
  left: 0;
  top: 0;
  padding: 8px 14px;
  background: rgba(var(--scrim), .72);
  color: #fff;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 1.4px;
  text-transform: uppercase;
}

.listing-body { padding: 22px 24px 26px; }

.listing-price {
  font-family: var(--display);
  font-weight: 300;
  font-size: 24px;
  letter-spacing: .02em;
}

.listing-addr {
  margin-top: 8px;
  font-size: 15px;
  line-height: 1.45;
}

.listing-sub {
  margin-top: 4px;
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.listing-specs {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  letter-spacing: 1.1px;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.listing-specs b {
  font-weight: 500;
  color: var(--ink);
}

.listing-empty,
.listing-loading {
  padding: 56px 0;
  text-align: center;
  color: var(--ink-soft);
}

.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  margin-top: 48px;
}

.pager-info {
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* The IDX line the shared MLS pool requires. Small, but never hidden. */
.idx-note {
  margin-top: 36px;
  font-size: 11px;
  line-height: 1.7;
  color: var(--ink-faint);
  max-width: 90ch;
}

/* ------------------------------------------------------------ neighborhoods */
.hood-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 28px;
}

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

@media (max-width: 560px) {
  .hood-grid { grid-template-columns: 1fr; }
}

.hood {
  min-width: 0;
}

.hood-media {
  aspect-ratio: 4 / 3;
  overflow: hidden;
}

.hood-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Hover scales the photo. No grayscale, ever. */
  transition: transform .6s var(--ease);
}

.hood:hover .hood-media img { transform: scale(1.04); }

.hood-label {
  margin-top: 18px;
  font-family: var(--display);
  font-weight: 300;
  font-size: 18px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #fff;
}

.hood-line {
  margin-top: 8px;
  font-size: 14px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .74);
}

/* ------------------------------------------------------------ testimonials */
.reviews {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 32px;
}

@media (max-width: 860px) {
  .reviews { grid-template-columns: 1fr; }
}

.review {
  min-width: 0;
  padding: 36px 34px;
  background: var(--paper);
  border: 1px solid var(--line);
}

.review-quote {
  font-size: 18px;
  line-height: 1.65;
  color: var(--ink);
}

.review-by {
  margin-top: 22px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.review-source {
  margin-top: 14px;
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ------------------------------------------------------------- blog cards */
.post-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
}

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

@media (max-width: 640px) {
  .post-grid { grid-template-columns: 1fr; }
}

.post-card {
  display: block;
  min-width: 0;
  text-decoration: none;
  color: var(--ink);
}

.post-media {
  aspect-ratio: 3 / 2;
  background: var(--sand);
  overflow: hidden;
}

.post-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .6s var(--ease);
}

.post-card:hover .post-media img { transform: scale(1.04); }

.post-date {
  margin-top: 20px;
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.post-title {
  margin-top: 10px;
  font-family: var(--display);
  font-weight: 300;
  font-size: 20px;
  letter-spacing: .04em;
  text-transform: uppercase;
  line-height: 1.3;
}

.post-excerpt {
  margin-top: 12px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-soft);
}

/* ------------------------------------------------------------ process steps */
.steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 28px;
}

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

@media (max-width: 640px) {
  .steps { grid-template-columns: 1fr; }
}

.step {
  min-width: 0;
  padding: 34px 30px 36px;
  background: var(--paper);
  border: 1px solid var(--line);
  transition: border-color .35s var(--ease), transform .35s var(--ease);
}

.step:hover {
  border-color: var(--ink);
  transform: translateY(-4px);
}

.step-n {
  font-family: var(--display);
  font-weight: 300;
  font-size: 40px;
  line-height: 1;
  color: var(--ink-faint);
}

.step-title {
  margin-top: 18px;
  font-family: var(--display);
  font-weight: 300;
  font-size: 19px;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.step-body {
  margin-top: 12px;
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink-soft);
}

/* ---------------------------------------------------------------- vendors */
.vendor-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px 32px;
}

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

@media (max-width: 640px) {
  .vendor-grid { grid-template-columns: 1fr; }
}

.vendor-trade { min-width: 0; }

.vendor-trade h3 {
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
  font-family: var(--display);
  font-weight: 300;
  font-size: 15px;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.vendor-list {
  list-style: none;
  margin-top: 16px;
}

.vendor-list li + li { margin-top: 14px; }

.vendor-name {
  font-size: 15px;
  font-weight: 500;
}

.vendor-meta {
  margin-top: 3px;
  font-size: 13px;
  color: var(--ink-soft);
}

.vendor-meta a { text-decoration: none; border-bottom: 1px solid var(--line); }

.vendor-note {
  margin-top: 44px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--ink-faint);
  max-width: 80ch;
}

/* ------------------------------------------------------------------ forms */
/* [CHECKLIST 2.5] Every grid field gets min-width:0 and every control gets
   width:100%. Without both, the columns refuse to shrink and the form
   overflows the phone sideways. */
.form {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  max-width: 900px;
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.form-field.is-wide { grid-column: 1 / -1; }

/* A form that sits inside a half-width split has about 580px to work with, and
   three columns of that leaves an email field 170px wide. Two columns is the
   right density there. */
.form.is-narrow { grid-template-columns: repeat(2, 1fr); }

.form-field label {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.form input,
.form select,
.form textarea {
  width: 100%;
  min-width: 0;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 15px;
  transition: border-color .3s var(--ease);
}

.form input:focus,
.form select:focus,
.form textarea:focus {
  border-color: var(--ink);
  outline: none;
}

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

/* [CHECKLIST 2.5] The submit gets its own auto-sized cell, never crammed into
   a field column. */
.form-actions {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 18px;
}

.form-consent {
  grid-column: 1 / -1;
  display: flex;
  gap: 12px;
  align-items: flex-start;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-soft);
}

.form-consent input {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  margin-top: 3px;
  padding: 0;
}

.form-check {
  grid-column: 1 / -1;
  display: flex;
  gap: 12px;
  align-items: center;
  font-size: 14px;
  color: var(--ink-soft);
}

.form-check input {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  padding: 0;
}

/* The honeypot. Off screen rather than display:none, which some bots skip. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-status {
  grid-column: 1 / -1;
  display: none;
  padding: 14px 16px;
  border: 1px solid var(--line);
  background: var(--paper);
  font-size: 14px;
}

.form-status.is-shown { display: block; }
.form-status.ok { border-color: var(--ink); }
.form-status.err { border-color: #B4402F; color: #B4402F; }

/* [CHECKLIST 2.5] 2 columns at 860px, 1 column at 560px. */
@media (max-width: 860px) {
  .form { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
  .form { grid-template-columns: 1fr; }
}

/* -------------------------------------------------------- search filters */
.filters {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 16px;
  align-items: end;
  margin-bottom: 44px;
}

.filters .form-field { min-width: 0; }

.filters input,
.filters select {
  width: 100%;
  min-width: 0;
  padding: 13px 14px;
  border: 1px solid var(--line);
  border-radius: 0;
  background: var(--paper);
  font-family: var(--body);
  font-size: 14px;
}

/* [CHECKLIST 2.5] The buttons get their own auto-sized row, never crammed into
   a field column where they would squeeze the selects beside them. */
.filters-actions {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  min-width: 0;
}

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

@media (max-width: 560px) {
  .filters { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------- mortgage calculator */
.calc {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 56px;
  align-items: start;
}

@media (max-width: 1024px) {
  .calc { grid-template-columns: 1fr; gap: 40px; }
}

.calc-inputs {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}

@media (max-width: 560px) {
  .calc-inputs { grid-template-columns: 1fr; }
}

.calc-result {
  padding: 38px 34px;
  background: var(--paper);
  border: 1px solid var(--line);
}

.calc-total {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(34px, 4.4vw, 52px);
  line-height: 1;
}

.calc-total-label {
  margin-top: 12px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.calc-rows {
  margin-top: 30px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
}

.calc-row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 9px 0;
  font-size: 14px;
  color: var(--ink-soft);
}

.calc-row b {
  font-weight: 500;
  color: var(--ink);
}

.calc-note {
  margin-top: 28px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--ink-faint);
  max-width: 80ch;
}

/* ---------------------------------------------------------------- homebot */
/* The embed is a third-party iframe. It is bounded here so it can never blow
   out the page width on a phone. */
.embed-frame {
  width: 100%;
  max-width: 100%;
  min-width: 0;
  overflow: hidden;
  background: var(--paper);
  border: 1px solid var(--line);
  padding: 28px;
}

.embed-frame iframe {
  width: 100%;
  max-width: 100%;
  border: 0;
  display: block;
}

.embed-placeholder {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  padding: 52px 34px;
  text-align: left;
}

/* -------------------------------------------------------------- CTA band */
/* PART 6: the closing band carries NO photograph. One image per slot and no
   reuse, so on a light editorial site a flat beige band reads as more
   confident than a repeated photo. */
.cta-band {
  background: var(--sand);
  padding: 104px 0;
  text-align: center;
}

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

/* ----------------------------------------------------------------- footer */
.footer {
  background: var(--dark);
  color: rgba(255, 255, 255, .8);
  padding: 76px 0 30px;
}

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

@media (max-width: 860px) {
  .footer-top { grid-template-columns: 1fr; gap: 36px; }
}

.footer-col { min-width: 0; }

.footer .wordmark-name { color: #fff; font-size: 22px; }
.footer .wordmark-sub { color: rgba(255, 255, 255, .6); }

.footer-tag {
  margin-top: 16px;
  font-size: 14px;
  line-height: 1.7;
  color: rgba(255, 255, 255, .72);
  max-width: 42ch;
}

.footer-head {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: #fff;
  margin-bottom: 18px;
}

.footer-nav {
  display: flex;
  flex-direction: column;
  gap: 11px;
}

.footer-nav a {
  font-size: 14px;
  text-decoration: none;
  color: rgba(255, 255, 255, .78);
  transition: color .25s linear;
}

.footer-nav a:hover { color: #fff; }

.footer-contact {
  font-style: normal;
  font-size: 14px;
  line-height: 1.9;
  color: rgba(255, 255, 255, .78);
}

.footer-contact a {
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, .3);
}

.socials {
  display: flex;
  gap: 14px;
  margin-top: 20px;
}

.socials a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border: 1px solid rgba(255, 255, 255, .28);
  color: #fff;
  transition: background-color .3s var(--ease), color .3s var(--ease);
}

.socials a:hover { background: #fff; color: var(--dark); }

.footer-legal {
  padding: 26px 0;
  border-bottom: 1px solid rgba(255, 255, 255, .16);
  font-size: 12px;
  line-height: 1.8;
  color: rgba(255, 255, 255, .66);
}

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 22px;
  padding-top: 26px;
  font-size: 12px;
  color: rgba(255, 255, 255, .62);
}

.footer-bottom a {
  text-decoration: none;
  color: rgba(255, 255, 255, .78);
}

.footer-bottom .spacer { flex: 1 1 auto; }

.eho {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

/* ------------------------------------------------------- confirm markers */
/* Nothing the client has not supplied is invented. Every outstanding value
   from PART 8 renders as one of these instead of a plausible-looking number. */
.confirm {
  display: inline-block;
  padding: 2px 8px;
  border: 1px dashed currentColor;
  font-family: var(--body);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: #8A6D1F;
  /* Deliberately NOT nowrap. That suits a two-word chip and is catastrophic
     for a sentence: one long inline chip pushed a previous build's document to
     691px on a 390px phone. Long text goes in .confirm-block. */
  white-space: normal;
}

.confirm-block {
  display: block;
  padding: 14px 16px;
  border: 1px dashed rgba(138, 109, 31, .55);
  background: rgba(138, 109, 31, .05);
  font-size: 13px;
  line-height: 1.65;
  color: #8A6D1F;
}

.section-dark .confirm,
.footer .confirm {
  color: #E4C56A;
  border-color: rgba(228, 197, 106, .6);
}

/* ------------------------------------------------------------------ reveal */
/* [CHECKLIST 2.8] Restrained: this is an elegant light site, not a showcase.
   Only armed once JS adds .js to <html>, so with scripts blocked every element
   stays at its default, which is fully visible. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity .7s var(--ease), transform .7s var(--ease);
}

.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
}

/* Photos scale from 1.04 to 1 on reveal. */
.js [data-reveal] .hood-media img,
.js [data-reveal].split-media img {
  transform: scale(1.04);
  transition: transform .9s var(--ease);
}

.js [data-reveal].is-in .hood-media img,
.js [data-reveal].is-in.split-media img {
  transform: none;
}

/* [CHECKLIST 2.8] The reduced motion guard wraps everything. Users who ask for
   less motion see final values immediately, including the stat counters. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
  html { scroll-behavior: auto; }
  .js [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ------------------------------------------------------------ legal pages */
.legal {
  padding: calc(var(--nav-h) + 72px) 0 96px;
}

.legal h2 {
  margin-top: 44px;
  font-family: var(--display);
  font-weight: 300;
  font-size: 20px;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.legal h2:first-of-type { margin-top: 32px; }

.legal p,
.legal li {
  color: var(--ink-soft);
  font-size: 15px;
  line-height: 1.75;
}

.legal p { margin-top: 14px; }

.legal ul {
  margin-top: 14px;
  padding-left: 20px;
  list-style: disc;
}

.legal li + li { margin-top: 8px; }

.legal .measure { max-width: 72ch; }
