/* ============================================
   GRADE LA — Cinematic Fullscreen Design System
   (based on Concept D)
   ============================================ */

:root{
  --ink:#353535;      /* primary dark — body copy, dark logo colourway */
  --white:#f9f7f3;    /* cream — page background, light logo colourway */
  --green:#4e544b;    /* forest — secondary brand colourway, sampled from the official logomark */
  --grey:#f9f7f3;
  --line:rgba(12,12,11,.1);
  --sans:'Lato', 'Helvetica Neue', Arial, sans-serif;   /* brand face — Lato */
  --header-h: 104px;        /* solid bone nav bar */
  --header-logo-h: 68px;    /* logo inside it, with breathing room */
  --header-pad: 60px;
}

/* ---------- Brand mark utility ----------
   Renders the Grade mark in ANY colour by masking with its alpha channel,
   so it always matches the inherited text colour. Use when the mark must
   adapt to its surroundings; use a fixed-colour PNG from img/logos/ when
   it must stay one specific colourway (as the home hero does).
   Set a height; width follows the mark's 300x182 ratio.
   Pair with a .sr-only "Grade" label — a masked div has no alt text.     */
.brand-mark{
  display:block; aspect-ratio:800 / 485; height:40px;
  background-color: currentColor;
  -webkit-mask: url('../img/logos/grade-mark-charcoal.png') no-repeat center / contain;
          mask: url('../img/logos/grade-mark-charcoal.png') no-repeat center / contain;
}
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}

*{ box-sizing: border-box; }
html{ scroll-behavior: smooth; }
body{
  margin:0;
  padding-top: var(--header-h);   /* clears the fixed header */
  background: var(--white);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 300;
  line-height: 1.6;
  font-size: 16px;
}
img{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
.label{ font-size:11px; font-weight:700; letter-spacing:.22em; text-transform:uppercase; opacity:.85; }
.wrap{ max-width:1500px; margin:0 auto; padding:0 60px; }
@media (max-width:800px){ .wrap{ padding:0 22px; } }

/* ---------- Header ----------
   A solid bone bar across the full width, always present. Replaces the old
   transparent-over-hero header that turned solid on scroll, so the logo now
   has its own field instead of sitting on live photography. */
header.site-header{
  position: fixed; top:0; left:0; right:0; z-index: 200;
  display:flex; align-items:center; justify-content:space-between;
  height: var(--header-h);
  padding: 0 var(--header-pad);
  background: var(--white);
  color: var(--ink);
  border-bottom: 1px solid rgba(0,0,0,.07);
}
.header-logo{ display:block; }
.header-logo img{ height: var(--header-logo-h); width:auto; display:block; }

.main-nav a{ letter-spacing:2px; text-transform:uppercase; padding-bottom:3px; border-bottom:1px solid transparent; }
.main-nav a:hover{ opacity:.6; }
.main-nav a.active{ border-bottom-color: currentColor; }
/* color:inherit is required — the UA stylesheet gives <button> its own color,
   so currentColor on the bars would render black instead of the header's color */
.nav-toggle{ display:block; position:relative; z-index:250; background:none; border:none; cursor:pointer; color:inherit; padding:0; }
.nav-toggle span{ display:block; width:29px; height:2px; background: currentColor; margin:7px 0; }   /* +20% overall, heavier bars; the home splash sets its own larger size */

/* Nav is a full-screen overlay at every width, opened by the hamburger */
.main-nav{
  position: fixed; inset: 0 0 0 0;
  background: var(--white); color: var(--ink);
  display:none; flex-direction:column; align-items:flex-start; justify-content:center;
  padding: 60px;
}
.main-nav.open{ display:flex; }
.main-nav ul{ display:flex; flex-direction:column; gap:22px; list-style:none; margin:0; padding:0; }
.main-nav a{ font-size:22px; color: var(--ink); }

@media (max-width:900px){
  :root{ --header-h:78px; --header-logo-h:50px; --header-pad:22px; }
  .main-nav{ padding: 60px 34px; }
  .main-nav a{ font-size:18px; }
}

/* ---------- Fullscreen hero ---------- */
.fs{
  position:relative; height:calc(100vh - var(--header-h)); background-size:cover; background-position:center;
  display:flex; align-items:center; justify-content:center; color: var(--white); overflow:hidden;
}
.fs.page{ height:calc(82vh - var(--header-h)); min-height:400px; align-items:flex-end; justify-content:flex-start; }
.fs::after{
  content:""; position:absolute; inset:0;
  background: linear-gradient(180deg, rgba(0,0,0,.28) 0%, rgba(0,0,0,.08) 30%, rgba(0,0,0,.55) 100%);
}
.fs.page::after{ background: linear-gradient(180deg, rgba(0,0,0,.25) 0%, rgba(0,0,0,.1) 40%, rgba(0,0,0,.6) 100%); }
.fs-center{ position:relative; z-index:2; text-align:center; }
.fs-center .label{ display:block; margin-bottom:22px; letter-spacing:8px; }
.fs-center h1{ font-size:clamp(48px,9vw,120px); font-weight:300; letter-spacing:2px; margin:0; }

.fs-caption{ position:relative; z-index:2; padding: 0 60px 34px; max-width:640px; }
@media (max-width:800px){ .fs-caption{ padding:0 22px 25px; } }
.fs-caption .label{ margin-bottom:16px; display:block; font-size:13px; }
/* the eyebrow now sits under the title, so its 16px belongs above it —
   and it needs a little more of it, since it is trailing rather than leading */
.fs-caption h1 + .label,
.fs-caption h2 + .label{ margin:18px 0 0; }
.fs-caption h1, .fs-caption h2{ font-size:clamp(34px,5.5vw,68px); font-weight:300; line-height:1.12; margin:0; }

.scroll-cue{
  position:absolute; bottom:36px; left:50%; transform:translateX(-50%); z-index:2; color: var(--white);
  font-size:10px; letter-spacing:3px; text-transform:uppercase; display:flex; flex-direction:column; align-items:center; gap:10px;
}
.scroll-cue .dash{ width:1px; height:40px; background: var(--white); opacity:.7; animation: pulse 1.8s ease-in-out infinite; }
@keyframes pulse{ 0%,100%{opacity:.2;} 50%{opacity:.9;} }

/* Mid-page full-bleed caption break (shorter than home hero) */
.break{ position:relative; height:72vh; background-size:cover; background-position:center; display:flex; align-items:flex-end; color: var(--white); overflow:hidden; }
.break::after{ content:""; position:absolute; inset:0; background: linear-gradient(180deg, rgba(0,0,0,.15) 0%, rgba(0,0,0,.05) 35%, rgba(0,0,0,.55) 100%); }

/* ---------- Split (two-column, full height) ---------- */
.split{ display:grid; grid-template-columns:1fr 1fr; min-height:100vh; }
.split.short{ min-height:auto; }
@media (max-width:900px){ .split{ grid-template-columns:1fr; min-height:auto; } }
.split.reverse .split-img{ order:2; }
@media (max-width:900px){ .split.reverse .split-img{ order:0; } }
.split-text{ display:flex; flex-direction:column; justify-content:center; padding:90px 80px; }
@media (max-width:800px){ .split-text{ padding:60px 22px; } }
.split-text .label{ margin-bottom:24px; }
.split-text h1,
.split-text h2{ font-size:clamp(30px,4vw,46px); font-weight:300; line-height:1.25; margin:0 0 26px; }
.split-text p{ font-size:16px; opacity:.78; max-width:460px; margin-bottom:20px; }
.split-text a.cta{ font-size:11px; letter-spacing:2px; text-transform:uppercase; border-bottom:1px solid var(--ink); padding-bottom:4px; align-self:flex-start; margin-top:14px; }
.split-img{ position:relative; overflow:hidden; min-height:420px; }
.split-img img{ width:100%; height:100%; object-fit:cover; position:absolute; inset:0; }
.split-img .logo-mark{ position:absolute; left:36px; bottom:32px; z-index:2; max-height:44px; filter:brightness(0) invert(1); opacity:.92; }

/* ---------- Tile grid (fullscreen project / listing tiles) ---------- */
.tile-row{ display:grid; min-height:100vh; }
.tile-row.cols-2{ grid-template-columns:1fr 1fr; }
.tile-row.cols-1{ grid-template-columns:1fr; }
@media (max-width:800px){ .tile-row{ min-height:auto; } .tile-row.cols-2{ grid-template-columns:1fr; } }
.tile{ position:relative; overflow:hidden; color: var(--white); display:block; min-height:56vh; }
.tile img{ width:100%; height:100%; object-fit:cover; position:absolute; inset:0; transition: transform .8s cubic-bezier(.2,.7,.2,1); }
.tile:hover img{ transform:scale(1.06); }
.tile::after{ content:""; position:absolute; inset:0; background: rgba(0,0,0,.22); transition: background .4s ease; }
.tile:hover::after{ background: rgba(0,0,0,.38); }
.tile-cap{ position:absolute; left:38px; bottom:20px; right:38px; z-index:2; }
.tile-cap .label{ margin-bottom:12px; display:block; }
.tile-cap h3{ font-size:clamp(24px,2.6vw,34px); font-weight:300; margin:0; }
.tile-status{ position:absolute; top:30px; right:34px; z-index:2; font-size:17px; letter-spacing:2px; text-transform:uppercase; font-weight:400; }
.tile-price{ font-size:13px; font-weight:700; letter-spacing:.22em; text-transform:uppercase;
             opacity:.85; margin-top:7px; }

/* ---------- Intro / index row ---------- */
.index-row{ padding:120px 60px 60px; max-width:1500px; margin:0 auto; }
@media (max-width:800px){ .index-row{ padding:80px 22px 40px; } }
.index-row .label{ display:block; margin-bottom:22px; }
.index-row h2{ font-size:clamp(26px,3.4vw,44px); font-weight:300; max-width:820px; margin:0 0 26px; line-height:1.3; }
.index-row p{ max-width:640px; opacity:.78; font-size:16px; margin-bottom:0; }

/* ---------- Portrait grid (team) ---------- */
.portrait-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:2px; background:var(--line); }
.portrait-grid + .portrait-grid{ margin-top:2px; }
.portrait-grid.cols-2{ grid-template-columns:repeat(2,1fr); max-width:750px; margin:0 auto; }
.portrait-grid.cols-3{ grid-template-columns:repeat(3,1fr); max-width:1125px; margin:0 auto; }
@media (max-width:900px){ .portrait-grid, .portrait-grid.cols-2, .portrait-grid.cols-3{ grid-template-columns:1fr 1fr; max-width:none; } }
@media (max-width:560px){ .portrait-grid, .portrait-grid.cols-2, .portrait-grid.cols-3{ grid-template-columns:1fr; max-width:none; } }
.portrait{ position:relative; aspect-ratio:3/4; overflow:hidden; background:var(--white); color:var(--white); }
.portrait img{ width:100%; height:100%; object-fit:cover; filter:grayscale(15%); transition: filter .4s ease, transform .6s ease; }
.portrait:hover img{ filter:grayscale(0%); transform:scale(1.04); }
.portrait::after{ content:""; position:absolute; inset:0; background:linear-gradient(0deg, rgba(0,0,0,.6), rgba(0,0,0,0) 45%); }
.portrait-cap{ position:absolute; left:24px; bottom:22px; right:24px; z-index:2; }
.portrait-cap h3{ font-size:16px; font-weight:400; letter-spacing:.5px; margin:0 0 4px; }
.portrait-cap p{ font-size:11px; letter-spacing:1px; text-transform:uppercase; opacity:.8; margin:0; }

/* ---------- CTA band ---------- */
.cta-band{ padding:180px 0; text-align:center; }
@media (max-width:800px){ .cta-band{ padding:110px 0; } }
.cta-band .label{ display:block; margin-bottom:24px; }
.cta-band h2{ font-size:clamp(30px,4.5vw,52px); font-weight:300; max-width:900px; margin:0 auto 34px; line-height:1.25; }
.cta-band a.cta{ font-size:11px; letter-spacing:2px; text-transform:uppercase; border-bottom:1px solid var(--ink); padding-bottom:4px; }

/* ---------- Forms (contact) ---------- */
.form-grid input, .form-grid textarea, .form-grid select{
  width:100%; background:transparent; border:none; border-bottom:1px solid rgba(12,12,11,.25);
  font-family: var(--sans); font-size:15px; padding:12px 2px; font-weight:300; color: var(--ink);
}
.form-grid input::placeholder, .form-grid textarea::placeholder{ color: rgba(53,53,53,.4); }
.form-grid textarea{ resize:none; height:80px; }
/* strip the native select chrome and draw our own caret to match the inputs */
.form-grid select{
  appearance:none; -webkit-appearance:none; border-radius:0; cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--ink) 50%),
                   linear-gradient(135deg,var(--ink) 50%,transparent 50%);
  background-position:calc(100% - 9px) calc(50% + 1px), calc(100% - 4px) calc(50% + 1px);
  background-size:5px 5px, 5px 5px; background-repeat:no-repeat;
  padding-right:26px;
}
.form-grid select:invalid{ color: rgba(53,53,53,.4); }   /* placeholder-ish until chosen */
.form-grid :focus-visible{ outline:2px solid var(--ink); outline-offset:3px; }
.btn-submit:disabled{ opacity:.5; cursor:default; }
/* Netlify honeypot — must exist in the DOM but never be seen */
.hp-field{ position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }
.form-row{ display:flex; gap:24px; }
@media (max-width:500px){ .form-row{ flex-direction:column; } }
.form-row .field{ flex:1; }
.form-grid{ display:flex; flex-direction:column; gap:26px; max-width:420px; }
.btn-submit{ align-self:flex-start; font-size:11px; letter-spacing:2px; text-transform:uppercase; padding:16px 40px; border:1px solid var(--ink); background:none; cursor:pointer; font-family:var(--sans); color:var(--ink); margin-top:6px; }
.btn-submit:hover{ background:var(--ink); color:var(--white); }
.work-list{ list-style:none; margin:0 0 30px; padding:0; }
.work-list li{ font-size:15px; padding:8px 0; opacity:.75; }

/* ---------- Home hero: triptych (no top nav on home; nav lives in the panels + footer) ---------- */
.hero-triptych{ background: var(--ink); }
.hero-triptych::after{ content:none; }

.hero-panels{
  position:absolute; inset:0; z-index:3;
  display:grid; grid-template-columns:repeat(3,1fr);
}
.hero-panel{
  position:relative; overflow:hidden;
  display:block;
  border-right:1px solid rgba(255,255,255,.4);
}
.hero-panel:last-child{ border-right:none; }
.hero-panel img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  transition: transform .8s cubic-bezier(.2,.7,.2,1);
}
.hero-panel:hover img{ transform:scale(1.06); }
.hero-panel .panel-tint{
  position:absolute; inset:0; background:rgba(0,0,0,0);
  transition: background .45s ease;
}
.hero-panel:hover .panel-tint{ background:rgba(0,0,0,.55); }
.hero-panel .panel-content{
  position:relative; z-index:2; height:100%;
  display:flex; flex-direction:column; align-items:center; justify-content:flex-end;
  text-align:center; padding:0 30px 90px; color:var(--white);
  text-shadow:0 1px 12px rgba(0,0,0,.35);
  transition: text-shadow .45s ease;
}
.hero-panel:hover .panel-content{ text-shadow:none; }
.hero-panel .p-num{ font-size:11px; letter-spacing:3px; opacity:.85; margin-bottom:14px; }
/* Lato Light — the brand face, used for the hero panel labels.
   Uppercase is set in CSS not markup so the accessible name stays
   "Development" rather than "DEVELOPMENT".
   NOTE: Lato is only loaded on index.html, the one page the triptych
   appears on. Reusing this face elsewhere means adding it there too. */
.hero-panel h2{
  font-size:clamp(19px,2.2vw,30px); font-weight:300;
  text-transform:uppercase; letter-spacing:.14em; margin:0 0 14px;
}
.hero-panel .p-link{
  font-size:10.5px; letter-spacing:2.5px; text-transform:uppercase;
  opacity:0; transform:translateY(6px);
  transition: opacity .35s ease, transform .35s ease;
}
.hero-panel:hover .p-link{ opacity:1; transform:translateY(0); }


@media (max-width:800px){
  .hero-panels{ grid-template-columns:1fr; grid-template-rows:repeat(3,1fr); }
  .hero-panel{ border-right:none; border-bottom:1px solid rgba(255,255,255,.4); }
  .hero-panel .panel-content{ padding-bottom:36px; }
  .hero-panel .p-link{ opacity:1; transform:none; }
}

/* ---------- Detail pages (project / listing / bio) ---------- */
.back-link{ display:inline-block; font-size:11px; letter-spacing:2px; text-transform:uppercase; opacity:.75; margin-bottom:20px; }
.back-link:hover{ opacity:1; }

.detail-stats{ display:flex; flex-wrap:wrap; max-width:1500px; margin:0 auto; border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
.detail-stats .stat{ flex:1 1 150px; padding:26px 30px; border-right:1px solid var(--line); }
.detail-stats .stat:last-child{ border-right:none; }
.detail-stats .stat .label{ display:block; margin-bottom:10px; }
.detail-stats .stat .value{ font-size:19px; font-weight:300; }
@media (max-width:800px){ .detail-stats .stat{ flex:1 1 45%; padding:20px 22px; } }

.gallery-grid{ display:grid; grid-template-columns:repeat(2,1fr); gap:2px; background:var(--line); }
.gallery-grid img{ width:100%; height:100%; object-fit:cover; aspect-ratio:4/3; display:block; }
@media (max-width:800px){ .gallery-grid{ grid-template-columns:1fr; } }

.bio-specialties{ list-style:none; margin:0 0 28px; padding:0; }
.bio-specialties li{ font-size:14px; padding:7px 0; border-bottom:1px solid var(--line); opacity:.75; }

/* ---------- Footer ---------- */
footer.site-footer{ padding:44px 0; border-top:1px solid var(--line); }
.footer-inner{ display:flex; justify-content:space-between; flex-wrap:wrap; gap:16px; font-size:11px; letter-spacing:1.5px; text-transform:uppercase; opacity:.75; }
.footer-inner a:hover{ opacity:1; }

/* ---------- Team bio contact block ---------- */
.bio-dre{ display:block; font-size:11px; letter-spacing:2px; opacity:.75; margin-top:10px; margin-bottom:22px; }
.bio-contact{ display:flex; flex-wrap:wrap; gap:26px; margin-top:26px; }
.bio-contact a{
  font-size:11px; letter-spacing:2px; text-transform:uppercase;
  border-bottom:1px solid var(--ink); padding-bottom:4px;
}
.bio-contact a:hover{ opacity:.6; }

/* ---------- Listing agent block ---------- */
.listing-agent h2{ font-size:20px; font-weight:400; margin:0; }
.listing-agent .bio-dre{ margin-bottom:14px; }


/* ---------- Home splash ----------
   The home page is the triptych alone. No header bar: the logo and the
   hamburger sit directly on the photography, per the approved mock-up.
   Applied via body.splash so every other page keeps the solid bone bar. */
body.splash{ padding-top:0; }
body.splash .site-header{
  background:none; border-bottom:none;
  height:auto; padding:35px var(--header-pad) 26px 34px;   /* 35px = where a 34px button lands
                                                              centred in the 104px bar elsewhere */
  align-items:flex-start;
}
body.splash .header-logo img{ height:95px; }    /* 112 - 15% */
/* the splash used to set its own oversized bars; it now inherits the same
   29x2px at 7px spacing as every other page. Only the colour differs. */
body.splash .fs{ height:100vh; }
body.splash .site-header{ color: var(--ink); }   /* hamburger matches the charcoal logo */
.hero-panel .panel-content{ color: var(--white); }

/* thin light seams between panels rather than a hairline border */
.hero-triptych{ background: var(--white); }
.hero-panels{ gap:0; }
.hero-panel{ border-right:none; }

/* captions sit bottom-left, with the link always visible */
.hero-panel .panel-content{
  align-items:flex-start; text-align:left;
  padding:0 46px 52px;
}
/* Rule is a fixed 1.3em — roughly two characters — so it is identical under
   all three titles rather than scaling with each word's length. */
.hero-panel h2{
  font-size:clamp(24px,2.7vw,40px); font-weight:300;   /* Lato Light */
  letter-spacing:.06em;
  margin:0 0 14px; padding-bottom:9px; position:relative;
}
.hero-panel h2::after{
  content:""; position:absolute; left:0; bottom:0;
  width:1.3em; height:1px; background:currentColor; opacity:.85;
}
.hero-panel .p-link{ opacity:1; transform:none; font-size:11.5px; }

/* a bottom scrim carries the caption instead of a text shadow */
.hero-panel .panel-tint{
  background: linear-gradient(180deg, rgba(0,0,0,.20) 0%, rgba(0,0,0,0) 34%, rgba(0,0,0,.62) 100%);
}
.hero-panel:hover .panel-tint{
  background: linear-gradient(180deg, rgba(0,0,0,.34) 0%, rgba(0,0,0,.18) 34%, rgba(0,0,0,.72) 100%);
}

@media (max-width:800px){
  body.splash .site-header{ padding:22px var(--header-pad) 22px; }
  .hero-panel .panel-content{ padding:0 24px 32px; }

  /* Mobile stacks the panels, so the logo and toggle sit on photography
     rather than the bright travertine that reads at desktop widths.
     Cream there, with a slightly stronger top scrim to carry it. */
  body.splash .site-header{ color: var(--white); }

  /* The 95px desktop logo is ~6% of a 1440px viewport but ~25% of a phone,
     where it crowded the Development caption. Scaled to sit at roughly the
     same share of the screen, with the toggle brought down to match. */
  body.splash .header-logo img{ height:62px; }
  body.splash .hero-panel .panel-tint{
    background: linear-gradient(180deg, rgba(0,0,0,.34) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,.62) 100%);
  }
}

/* ---------- Phase list (Development: what Grade oversees) ---------- */
/* The six phases run in order — acquisition really does precede entitlements —
   so they are an <ol>, and the counter plus the connecting spine make that
   sequence visible instead of reading as an unordered capability list. */
.phase-list{ list-style:none; margin:0 0 30px; padding:0; max-width:420px; counter-reset:phase; }
.phase-list li{
  counter-increment:phase; position:relative;
  padding:0 0 26px 42px;
}
/* The numeral sits on the same baseline as its phase and at the same size,
   so the two read as one line rather than a marker above a label. */
.phase-list li::before{
  content:counter(phase, decimal-leading-zero);
  position:absolute; left:0; top:0;
  font-size:inherit; line-height:inherit; letter-spacing:.04em;
  color:var(--green);
}
/* the spine: a hairline from below this numeral down to the next */
.phase-list li::after{
  content:""; position:absolute; left:12px; top:34px; bottom:0; width:1px;
  background:var(--line);
}
.phase-list li:last-child{ padding-bottom:0; }
.phase-list li:last-child::after{ display:none; }

/* ---------- Section heading (Brokerage: Active / Sold) ---------- */
.section-head{
  max-width:1500px; margin:0 auto; padding:70px 60px 26px;
  border-bottom:1px solid var(--line);
}
.section-head .label{ display:block; }
@media (max-width:800px){ .section-head{ padding:48px 22px 20px; } }

/* ---------- Project detail: full-height cover ---------- */
.fs.page.cover{ height:calc(100vh - var(--header-h)); }
.fs.page.cover .fs-caption h1{ font-size:clamp(28px,4.4vw,54px); }  /* ~20% down */

/* stats span the full page width */
.detail-stats.full{ max-width:none; }

/* narrative column matches the stats gutter; image matches the text height */
.split.project-about{ min-height:0; align-items:stretch; }
.split.project-about .split-text{ padding:70px 60px; }
.split.project-about .split-text h2{ font-size:clamp(21px,2.8vw,32px); }  /* ~30% down */
.split.project-about .split-text p{ max-width:none; }
.split.project-about .split-img{ min-height:0; }
@media (max-width:800px){ .split.project-about .split-text{ padding:48px 22px; } }

/* gallery with no seams */
.gallery-grid.flush{ gap:0; background:none; }

/* Left-align a centered max-width block with the full-bleed .split gutter.
   .index-row / .section-head are capped at 1500px and auto-centred, so on wide
   screens their left edge sits inboard of .split-text's 60px padding. */
.index-row.flush-left, .section-head.flush-left{ max-width:none; margin:0; }

/* 15% smaller again (was clamp(21px,2.8vw,32px)) */
.split.project-about .split-text h2{ font-size:clamp(18px,2.4vw,27px); }

/* Closing CTA: no eyebrow, headline matched to the About headline, less air */
.cta-band.tight{ padding:96px 0; }
.cta-band.tight h2{ font-size:clamp(18px,2.4vw,27px); margin-bottom:26px; }
@media (max-width:800px){ .cta-band.tight{ padding:64px 0; } }

/* Hero photo as a real <img> rather than a CSS background, so it can carry
   srcset and a priority hint. Sits below .fs::after (generated last, so it
   paints above) and below .fs-caption, which holds z-index:2. */
.fs-bg{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; object-position:center; z-index:0;
}

/* ---------- Mobile legibility ----------
   Lato Light at 16px is thin on a phone, and the low-opacity body copy that
   reads as "quiet" on a large bright screen reads as "faint" on a handset in
   daylight. Body text goes to regular weight and the opacities move close to
   solid. Headings stay at 300 — they are large and already full contrast. */
@media (max-width:800px){
  body{ font-weight:400; }
  .split-text p,
  .index-row p,
  .work-list li,
  .bio-specialties li,
  .portrait-cap p{ opacity:.92; }
  /* .phase-list li is deliberately absent — it is full opacity at every width */

  .label,
  .tile-price,
  .back-link,
  .bio-dre,
  .footer-inner{ opacity:1; }
}

/* ---------- Project detail: the same --sec-gap rhythm ----------
   Every boundary on the page lands on --sec-gap. Which side supplies it
   depends on the neighbour: the cover, the stats band and the gallery grid
   have no vertical padding of their own, so the section after each of them
   takes the whole gap. */
.detail-stats.full{ margin-top:var(--sec-gap); }                 /* cover -> stats */
.split.project-about .split-text{ padding:var(--sec-gap) 60px; } /* stats -> about, about -> gallery */
@media (max-width:800px){ .split.project-about .split-text{ padding:var(--sec-gap) 22px; } }
.split.project-about + .section-head{ padding-top:0; }           /* the split already supplied it */

/* the back link now closes the description, so it needs the spacing a CTA had */
.split.project-about .split-text .back-link{ align-self:flex-start; margin:14px 0 0; }

/* Option B: the image beside the description is inset by the same --sec-gap the
   text column uses, so photo and copy occupy one optical box — the top of the
   image lines up with the first line of text, the bottom with the last. Without
   this the column stretches the full row and its top edge lands exactly on the
   stats band's bottom rule, which then reads as part of the photograph.

   It has to be set on the <img>, not as padding on .split-img: the image is
   absolutely positioned, and inset:0 resolves against the PADDING box, so
   padding on the column would not move it at all. */
/* The height has to be COMPUTED, and this took two attempts to get right.
   The base rule sets height:100%. An absolutely positioned box with top,
   bottom and height is over-constrained, so CSS discards `bottom` — the image
   was inset at the top only, ran 60px past its column, and overflow:hidden
   clipped it flush, leaving no gap beneath it at all.
   height:auto does not fix it either: for a REPLACED element like <img>,
   auto resolves to the intrinsic height (width ÷ aspect ratio) rather than
   stretching between top and bottom, which left a 226px gap instead of 60.
   Subtracting the two insets from 100% is what actually pins both edges. */
body.page-project .split-img img{
  inset: var(--sec-gap) 0;
  height: calc(100% - (var(--sec-gap) * 2));
}
@media (max-width:900px){
  body.page-project .split-img img{
    inset: var(--sec-half) 0;
    height: calc(100% - (var(--sec-half) * 2));
  }
}

/* a bare back link under the gallery — no heading rule beneath it */
.section-head.no-rule{ border-bottom:none; padding:21px 60px 0; }
@media (max-width:800px){ .section-head.no-rule{ padding:21px 22px 0; } }
/* ...and it supplies nothing below, so the closing band takes the full gap */
.section-head.no-rule + .cta-band.tight{ padding:var(--sec-gap) 0; }

/* closing CTA headline, 20% down from the About headline */
.cta-band.tight h2{ font-size:clamp(14px,1.9vw,22px); }

/* ---------- Standard page treatment ----------
   Applied via body.page-std to the main marketing pages: development, about,
   brokerage, capital, partnerships, contact. One rhythm and one type scale
   across all of them.

   Spacing: --sec-gap is the gap that should appear between any two sections.
   A full-bleed hero or a tile row contributes no padding of its own, so a
   boundary against one of those takes the whole gap from a single side;
   between two padded sections each contributes --sec-half and they add up to
   the same figure. Getting this wrong is what made the gaps read as double. */
:root{ --sec-gap:60px; --sec-half:30px; }

/* the cover runs the full height of the viewport, with a smaller title */
body.page-std .fs.page{ height:calc(100vh - var(--header-h)); }
body.page-std .fs-caption h1,
body.page-std .fs-caption h2{ font-size:clamp(28px,4.4vw,54px); }

body.page-std .index-row{ padding:var(--sec-gap) 60px var(--sec-half); }
body.page-std .index-row .label{ font-size:13px; }
body.page-std .index-row h2{ font-size:clamp(20px,2.64vw,30px); max-width:840px; }
body.page-std .index-row p{ font-size:17.6px; max-width:1080px; margin-bottom:18px; }
body.page-std .index-row p:last-child{ margin-bottom:0; }

body.page-std .split{ min-height:0; align-items:center; }
body.page-std .split-text{ padding:var(--sec-half) 80px; }
body.page-std .split-text .label{ font-size:13px; }
body.page-std .split-text h2{ font-size:clamp(20px,2.64vw,30px); }
body.page-std .split-text p{ font-size:17.6px; max-width:690px; }
/* The image is 98% of the text column's height and centred against it. Because
   the text is also centred in that column, the gap above the first line and the
   gap below the last resolve to the same value on their own. */
body.page-std .split-img{ min-height:0; height:98%; align-self:center; }
@media (max-width:900px){
  body.page-std .split-img{ height:auto; min-height:320px; }
}
@media (max-width:800px){ body.page-std .split-text{ padding:var(--sec-half) 22px; } }

body.page-std .section-head{ padding:var(--sec-half) 60px 26px; }
body.page-std .cta-band{ padding:var(--sec-gap) 0; }
body.page-std .cta-band .label{ font-size:13px; }
body.page-std .cta-band h2{ font-size:clamp(14px,1.9vw,22px); }

/* Development only: Our Approach is centred, and its phase list is wider */
.index-row.approach.centered{ text-align:center; }
.index-row.approach.centered .label,
.index-row.approach.centered h2,
.index-row.approach.centered p{ margin-left:auto; margin-right:auto; }
.split.oversee .phase-list{ max-width:630px; }
.split.oversee .phase-list li{ font-size:17.6px; }

/* Our Portfolio heading, on the same gutter as What We Oversee */
body.page-std .section-head.oversee-aligned{ max-width:none; margin:0; padding:68px 80px 18px; border-bottom:none; }
.section-head.oversee-aligned .label{ font-size:13px; }
@media (max-width:800px){ body.page-std .section-head.oversee-aligned{ padding:var(--sec-half) 22px 20px; } }

/* project type reads as a caption beneath the project name */
.tile-cap h3 + .label{ display:block; margin-top:7px; opacity:.85; font-size:13px; letter-spacing:.22em; }


/* a second agent on a co-listing — separated from the first by a rule rather
   than a heading, so neither reads as the primary contact */
.listing-agent h2.colisting{
  margin-top:34px; padding-top:30px; border-top:1px solid var(--line);
}

/* A gallery of one. The grid is two columns, so a lone image would sit in the
   left half with dead space beside it — it spans instead. */
.gallery-grid.flush img:only-child{ grid-column:1 / -1; aspect-ratio:16/9; }

/* ---------- Property film ----------
   A facade, not an embed. The Vimeo player is ~700KB of script; loading it on
   every visit to pay for a film most visitors will not open would give back a
   good part of the LCP work. This is our own poster image, served through the
   same responsive pipeline as every other photograph, and the iframe is
   injected only on click (js/main.js). */
.film-band{ display:block; }
.film{
  display:block; position:relative; width:100%; padding:0; border:none;
  background:none; cursor:pointer; overflow:hidden; aspect-ratio:16/9;
  color:inherit; font:inherit;
}
.film img{ width:100%; height:100%; object-fit:cover; display:block; }
.film-scrim{
  position:absolute; inset:0;
  background:linear-gradient(180deg,rgba(0,0,0,.18) 0%,rgba(0,0,0,.05) 40%,rgba(0,0,0,.45) 100%);
}
.film-play{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  width:84px; height:84px; border-radius:50%;
  border:1px solid rgba(255,255,255,.85); background:rgba(0,0,0,.18);
  display:grid; place-items:center;
  transition:background .3s ease, transform .3s ease;
}
.film-play::after{
  content:""; margin-left:5px;
  border-left:19px solid #fff; border-top:12px solid transparent; border-bottom:12px solid transparent;
}
.film:hover .film-play,
.film:focus-visible .film-play{ background:rgba(0,0,0,.42); transform:translate(-50%,-50%) scale(1.06); }
.film:focus-visible{ outline:2px solid var(--white); outline-offset:-6px; }
.film-runtime{
  position:absolute; right:26px; bottom:22px; color:#fff;
  font-size:11px; letter-spacing:.22em; text-transform:uppercase; font-weight:700; opacity:.9;
}
@media (max-width:800px){ .film-play{ width:62px; height:62px; } }
@media (prefers-reduced-motion: reduce){ .film-play{ transition:none; } }

/* once clicked, the iframe replaces the poster in the same box */
.film-band iframe{ display:block; width:100%; aspect-ratio:16/9; border:0; }

/* ---------- A statement band with no photograph behind it ----------
   The About page closed on a line set over an image. Without the image it is
   just a sentence, so it gets the weight of a section headline and the page's
   own ground rather than a scrim. */
.statement{
  padding:var(--sec-gap) 60px;
  text-align:center;
}
.statement h2{
  font-size:clamp(20px,2.64vw,30px); font-weight:300; line-height:1.3;
  max-width:900px; margin:0 auto;
}
@media (max-width:800px){ .statement{ padding:var(--sec-gap) 22px; } }

/* closing bands carry a centred label like every other section */
body.page-std .cta-band .label{ display:block; margin-bottom:24px; font-size:13px; }

/* The gap between the last line of Our Approach and the kitchen image should
   match the 60px above Our Approach. The index-row below contributes 30px, and
   the image is inset only ~1% of the row (about 7px), so the gap read as ~37px.
   Insetting the image by --sec-half instead makes the two sides add to 60. */
body.page-std .split.oversee .split-img{ height:calc(100% - (var(--sec-half) * 2)); }

/* ---------- Taller split images, with the copy centred against them ----------
   Measured live at 1707px wide, then converted to vw so they scale:

     About       image rendered 544px -> 598px  (+10%)
     Brokerage   image rendered 413px -> 537px  (+30%)
     Capital     image rendered 504px -> 605px  (+20%)

   The row is normally sized by the text column, and the image is 98% of that.
   Giving the image column a min-height taller than the text makes IT drive the
   row, and .split-text's justify-content:center then centres the copy against
   the image rather than the other way round. Below 900px the split stacks and
   the existing 320px min-height takes over. */
@media (min-width:901px){
  body.page-std .split.discipline .split-img{ min-height:35.7vw; }
  body.page-std .split.sellers    .split-img{ min-height:32.1vw; }
  body.page-std .split.buyers     .split-img{ min-height:32.1vw; }
  body.page-std .split.underwrite .split-img{ min-height:36.1vw; }
}

/* ---------- Crop position, chosen per photograph ----------
   Every other cover is a landscape exterior, where centring is right. The
   About cover is a double-height entry: the arch and the pendant installation
   are its subject and they sit in the top third. In a hero box of roughly 2:1
   a centred crop removed 218px from the top — the arch and chandelier — and
   kept 218px of floor. Biasing the crop upward keeps the subject. */

/* About: the closing statement sits closer to the band beneath it. The gap was
   60px from the statement plus 96px from the band — 156px. Halved to 78. */
.statement{ padding-bottom:30px; }
.statement + .cta-band.tight{ padding-top:48px; }

/* Brokerage: 60px between the For Sellers and For Buyers images, matching the
   gap between the cover and Our Approach. The image keeps the panel's top edge
   and is shortened by the full 60px, so all the slack sits below it — that one
   band is the whole gap. (It is NOT 30px from each of the two sections; the
   panels are flush.) The min-height carries the same 60px so the pictures keep
   the height they had. */
@media (min-width:901px){
  /* The picture is the panel minus its two 30px insets, so taking 10% off the
     picture means shrinking that part alone and adding the insets back — not
     scaling the whole panel, which would eat into the 60px gap as well. */
  body.page-std .split.sellers .split-img,
  body.page-std .split.buyers  .split-img{
    min-height: calc((35.6vw - (var(--sec-half) * 2)) * 0.9 + (var(--sec-half) * 2));
  }
  body.page-std .split.sellers .split-img img,
  body.page-std .split.buyers  .split-img img{ height:calc(100% - (var(--sec-half) * 2)); }
}

/* ---------- Team: portraits stand apart ----------
   The grid was a 2px hairline on a rule colour, so the five portraits read as
   one continuous block. One token, --sec-half, sets the space between the two
   on the top line, between the three on the bottom, and between the lines — the
   brief asked for the same chunk in all three places, so it is the same value
   rather than three that happen to match. The ground shows through instead of
   the rule colour, or the space would read as a thick border. */
.portrait-grid{ gap:var(--sec-half); background:none; }
.portrait-grid + .portrait-grid{ margin-top:var(--sec-half); }
@media (max-width:560px){ .portrait-grid{ gap:var(--sec-half); } }

/* The name at roughly double its old 16px, in Lato light. The floor keeps it
   from overrunning a narrow column before the grid drops to one per row. */
.portrait-cap h3{ font-size:clamp(22px,2.2vw,32px); font-weight:300; letter-spacing:.5px; margin:0; }
/* The role is set exactly like a project type on Development ("Extensive
   Remodel") — same size, weight, tracking and offset. */
.portrait-cap p{
  font-size:13px; font-weight:700; letter-spacing:.22em; text-transform:uppercase;
  opacity:.85; margin:7px 0 0;
}

/* ---------- Partnerships: the partner photograph, 30% taller ----------
   The row is normally sized by the text column and the image is 98% of it.
   A min-height taller than the text makes the image drive the row, and
   .split-text's justify-content:center then centres the copy against it —
   the same mechanism as About, Brokerage and Capital.

   Each partner's copy is a different length, so each starts from a different
   height and needs its own figure — measured at 1707px wide, x1.3, in vw.
   The min-height sets the container and the photograph fills it, so the figure
   is the wanted height directly; scaling it up for the container's 98% first
   overshot every one of these to 1.33x.

     Carolwood   472px -> 614px      Harrison    359px -> 467px
     Costa       424px -> 551px      Technogym   332px -> 431px  */
@media (min-width:901px){
  body.page-std .split.partner.carolwood .split-img{ min-height:35.97vw; }
  body.page-std .split.partner.costa     .split-img{ min-height:32.28vw; }
  body.page-std .split.partner.harrison  .split-img{ min-height:27.36vw; }
  body.page-std .split.partner.technogym .split-img{ min-height:25.25vw; }
}

/* ---------- Contact ----------
   The cover used to run straight into the photograph beside the form. This
   opens the same 60px between them that Development leaves between its cover
   and Our Approach: the image is shortened by that much and pinned to the
   bottom, so all the slack lands at the top where the gap is wanted. */
@media (min-width:901px){
  body.page-std .split.ways .split-img{
    height:calc(100% - var(--sec-gap)); align-self:end;
  }
}

/* The four ways to work, as the numbered index Development uses for its phases:
   green leading-zero numeral, name, and a line of copy. Two columns so the
   block sits beside the form rather than pushing it down the page. */
.work-grid{
  list-style:none; margin:0 0 46px; padding:0; counter-reset:way;
  display:grid; grid-template-columns:1fr 1fr; gap:30px 34px; max-width:560px;
}
@media (max-width:600px){ .work-grid{ grid-template-columns:1fr; gap:26px; } }
.work-grid li{ counter-increment:way; position:relative; padding-top:26px; }
.work-grid li::before{
  content:counter(way, decimal-leading-zero);
  position:absolute; left:0; top:0;
  font-size:13px; font-weight:700; letter-spacing:.22em; color:var(--green);
}
/* a hairline picks the numeral out of the copy beneath it */
.work-grid li::after{
  content:""; position:absolute; left:0; top:19px; width:22px; height:1px;
  background:var(--green); opacity:.45;
}
/* These were h3 until the heading order was fixed. As h2 they land inside
   body.page-std .split-text h2 (0,2,1), which sets a 30px section headline —
   so the rule that keeps them at caption size has to match that weight. */
body.page-std .work-grid h2,
.work-grid h2{ font-size:17px; font-weight:300; letter-spacing:.3px; margin:0 0 6px; line-height:1.3; }
.work-grid p{ font-size:14px; opacity:.72; margin:0; line-height:1.55; max-width:none; }

/* ---------- Home: the triptych is now the top of a page, not the whole page ----------
   The splash header is transparent and sits directly on the photography. Once
   there is cream content below, that header scrolls over it: on desktop the
   charcoal mark survives, but on mobile the cream mark disappears against the
   cream ground. So the header takes the standard solid bar the moment the page
   moves, which also brings the oversized splash logo down to the 68px every
   other page uses. js/main.js adds .solid past 40px. */
body.splash .site-header{ transition:background .35s ease, height .35s ease, padding .35s ease; }
body.splash .site-header.solid{
  background:var(--white); border-bottom:1px solid rgba(0,0,0,.07);
  height:var(--header-h); padding:0 var(--header-pad);
  align-items:center; color:var(--ink);
}
body.splash .site-header.solid .header-logo img{ height:var(--header-logo-h); }

/* Only the home page carries two lockups; every other page keeps its single
   charcoal one, so nothing else pays for the second file. */
.header-logo .lockup-cream{ display:none; }
@media (max-width:800px){
  body.splash .header-logo .lockup-ink{ display:none; }
  body.splash .header-logo .lockup-cream{ display:block; }
  body.splash .site-header.solid .header-logo .lockup-ink{ display:block; }
  body.splash .site-header.solid .header-logo .lockup-cream{ display:none; }
}

/* The cue belongs to the photography, so it stays cream even though the
   header above it turns charcoal. It retires once the reader has taken the
   hint rather than sitting under the content it pointed at. */
body.splash .scroll-cue{ transition:opacity .3s ease; }
body.splash.scrolled .scroll-cue{ opacity:0; pointer-events:none; }
@media (prefers-reduced-motion: reduce){
  body.splash .site-header,
  body.splash .scroll-cue{ transition:none; }
}

/* The intro's link needs the space a paragraph's margin does not give it */
.index-row.approach.centered a.cta{
  display:inline-block; margin-top:26px;
  font-size:11px; letter-spacing:2px; text-transform:uppercase;
  border-bottom:1px solid var(--ink); padding-bottom:4px;
}

/* ---------- Nav overlay, centred ----------
   The overlay filled the screen but stacked its links against the left edge,
   which read as a column that had lost its page rather than a menu. Centring
   needs both axes: the <ul> is itself a flex column, so align-items on the
   overlay alone would centre the list while leaving the links ragged inside it. */
.main-nav{ align-items:center; text-align:center; }
.main-nav ul{ align-items:center; }

/* ---------- Skip link ----------
   The first thing a keyboard reaches on every page, and the only thing that is
   invisible until focused. Without it, reaching the content means tabbing past
   the logo, eight nav links and the menu button on every single page. */
.skip-link{
  position:absolute; left:-9999px; top:0; z-index:300;
  background:var(--ink); color:var(--white);
  padding:14px 22px; font-size:11px; letter-spacing:2px; text-transform:uppercase;
}
.skip-link:focus{ left:0; }

/* The 404 and thank-you pages show one heading each. It was marked up as an h2,
   which left both pages with no h1 at all; it is an h1 now and inherits the
   band's type rather than carrying its own. */
.cta-band h1{
  font-size:clamp(30px,4.5vw,52px); font-weight:300;
  max-width:900px; margin:0 auto 34px; line-height:1.25;
}
