/* ==========================================================================
   Daniel Fischpan Real Estate
   Monochrome-luxe scroll site. The brand mark is pure black/white, so the
   whole identity rests on one warm brass accent, generous negative space and
   a high-contrast serif — the register Sotheby's/The Agency use, and the
   opposite of the stock realtor template.
   ========================================================================== */

:root{
  --ink:      #0b0c0e;   /* near-black ground                     */
  --ink-2:    #14161a;   /* raised surface                        */
  --ink-3:    #1e2126;   /* hairline / border                     */
  --bone:     #f4f1ec;   /* warm paper                            */
  --bone-2:   #e8e3da;
  --mute:     #9aa0a6;   /* secondary text on dark                */
  --mute-d:   #6b6560;   /* secondary text on light               */
  --brass:    #b58b52;   /* the single accent                     */
  --brass-lt: #d8b483;

  --shell: min(1440px, 100% - 8vw);
  --nav-h: 70px;                 /* measured height of the condensed fixed bar */
  --r: 2px;                      /* almost-square corners read as architectural */
  --section: clamp(6rem,13vh,10rem);  /* one gap between rooms, used everywhere  */
  --seam: clamp(7rem,17vh,13rem);     /* distance a full-bleed photo dissolves    */
  --ease: cubic-bezier(.22,.61,.36,1);
  --slow: cubic-bezier(.16,1,.3,1);

  --f-display: "Fraunces", "Fraunces fallback", Georgia, serif;
  --f-ui: "Inter", "Inter fallback", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
}

/* Metric-matched fallbacks. Both webfonts arrive after first paint, and swapping a fallback
   of a different width reflows the hero and the nav -- that swap was the site's entire CLS
   (0.0442, sources: .hero__inner and .nav__cta, at 240ms, i.e. right at FCP).
   The size-adjust values are measured, not copied: canvas measureText of the same string at
   the same size gave Fraunces/Georgia = 86.36% and Inter/Helvetica = 106.31%. */
@font-face{
  font-family:"Fraunces fallback";
  src:local("Georgia"), local("Times New Roman"), local("Iowan Old Style");
  size-adjust:86.36%;
  font-display:swap;
}
@font-face{
  font-family:"Inter fallback";
  src:local("Helvetica Neue"), local("Arial");
  size-adjust:106.31%;
  font-display:swap;
}

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

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

body{
  margin:0;
  background:var(--ink);
  color:var(--bone);
  font-family:var(--f-ui);
  font-size:clamp(15px,.55vw + 13px,17px);
  line-height:1.65;
  font-weight:300;
  letter-spacing:.005em;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

/* height:auto is load-bearing, not boilerplate. The SEO pass added intrinsic width/height
   attributes to every image to reserve layout space and kill CLS; without this rule those
   attributes are applied as literal CSS pixel heights, so any image whose CSS width differs
   from its attribute width gets a box of the wrong shape. That squashed the portrait cut-out
   into an ellipse and forced the great-room photo into a slot twice its designed height. */
img{ display:block; max-width:100%; height:auto; }
a{ color:inherit; text-decoration:none; }

h1,h2,h3{
  font-family:var(--f-display);
  font-weight:300;
  line-height:1.02;
  letter-spacing:-.022em;
  margin:0;
  font-variation-settings:"opsz" 100, "SOFT" 0, "WONK" 0;
}
h2{ font-size:clamp(2.1rem,4.6vw,4rem); }
h3{ font-size:clamp(1.25rem,1.7vw,1.6rem); letter-spacing:-.015em; }
p{ margin:0 0 1.1em; }

.skip{
  position:absolute; left:-9999px; top:0; z-index:200;
  background:var(--brass); color:#000; padding:.7rem 1.1rem;
}
.skip:focus{ left:1rem; top:1rem; }

::selection{ background:var(--brass); color:#000; }

/* ---------- shared atoms ------------------------------------------------ */

.eyebrow,.section-label{
  font-family:var(--f-ui);
  font-size:.72rem; font-weight:500;
  letter-spacing:.24em; text-transform:uppercase;
  color:var(--brass);
  margin:0 0 1.4rem;
}
.section-label{ display:flex; align-items:center; gap:.9rem; }
.section-label::before{
  content:""; width:2.4rem; height:1px; background:var(--brass); opacity:.55; flex:none;
}

.btn{
  display:inline-flex; align-items:center; justify-content:center;
  padding:1rem 1.9rem;
  background:var(--brass); color:#0b0c0e;
  font-family:var(--f-ui); font-size:.78rem; font-weight:600;
  letter-spacing:.14em; text-transform:uppercase;
  border:1px solid var(--brass); border-radius:var(--r); cursor:pointer;
  transition:background .45s var(--ease), color .45s var(--ease), transform .45s var(--ease);
}
.btn:hover{ background:var(--brass-lt); border-color:var(--brass-lt); transform:translateY(-2px); }
.btn--ghost{ background:transparent; color:var(--bone); border-color:rgba(244,241,236,.28); }
.btn--ghost:hover{ background:var(--bone); color:var(--ink); border-color:var(--bone); }
.btn--sm{ padding:.62rem 1.1rem; font-size:.68rem; }

.link-arrow{
  display:inline-flex; align-items:center; gap:.6rem;
  font-size:.78rem; font-weight:500; letter-spacing:.14em; text-transform:uppercase;
  color:var(--brass);
  padding-bottom:.35rem; border-bottom:1px solid rgba(181,139,82,.32);
  transition:gap .4s var(--ease), border-color .4s var(--ease);
}
.link-arrow:hover{ gap:1.05rem; border-color:var(--brass); }
.link-arrow + .link-arrow{ margin-top:.9rem; }

/* scroll-reveal — transform only, so it never triggers layout */
.reveal{
  opacity:0; transform:translateY(26px);
  transition:opacity 1s var(--slow), transform 1s var(--slow);
  transition-delay:var(--d,0ms);
}
.reveal.in{ opacity:1; transform:none; }

/* ---------- entrance choreography ---------------------------------------
   One entrance for every element reads as a slide deck: each new screen is a slab that
   arrives all at once. A walk-through is layered — the room settles behind you while the
   caption arrives in front of you. Four arrivals off the same observer:

     media      opens from a clipped frame, slowest, so the photograph feels uncovered
     heading    more travel and more weight than body copy, so it leads the paragraph
     label      slips in sideways and draws its own rule out to full width
     body       the original quick rise, unchanged

   All of it is opacity / transform / clip-path, so none of it touches layout. */

.reveal--media{
  opacity:0; transform:none;
  clip-path:inset(16% 0 0 0);
  transition:opacity 1.1s var(--slow), clip-path 1.45s var(--slow);
  transition-delay:var(--d,0ms);
  will-change:clip-path;
}
.reveal--media.in{ opacity:1; clip-path:inset(0 0 0 0); }
/* For a frame something deliberately hangs out of. clip-path clips to the border box, so a
   plain inset(0) would permanently shave the portrait cut-out where it overhangs to the right. */
.reveal--media.reveal--bleed{ clip-path:inset(16% -16% 0 0); }
.reveal--media.reveal--bleed.in{ clip-path:inset(0 -16% 0 0); }

h2.reveal{ transform:translateY(40px); transition-duration:1.25s, 1.25s; }

.section-label.reveal{ transform:translateX(-18px); }
.section-label.reveal::before{
  transform:scaleX(0); transform-origin:left center;
  transition:transform .95s var(--slow);
  transition-delay:calc(var(--d,0ms) + 140ms);
}
.section-label.reveal.in::before{ transform:scaleX(1); }

/* The hero is above the fold and its subhead is the Largest Contentful Paint element. A 1s
   fade-in is measured as 1s of LCP -- Core Web Vitals does not care that it was deliberate.
   Halving it inside the hero only costs a little unhurriedness and buys ~600ms of LCP. */
.hero .reveal{ transition-duration:.42s, .42s; }

/* ---------- nav --------------------------------------------------------- */

.nav{
  position:fixed; inset:0 0 auto 0; z-index:100;
  display:flex; align-items:center; gap:2rem;
  padding:1.5rem max(4vw,1.25rem);
  transition:background .5s var(--ease), padding .5s var(--ease),
             border-color .5s var(--ease), backdrop-filter .5s var(--ease);
  border-bottom:1px solid transparent;
}
.nav.stuck{
  background:rgba(11,12,14,.82);
  backdrop-filter:blur(18px) saturate(140%);
  -webkit-backdrop-filter:blur(18px) saturate(140%);
  border-bottom-color:var(--ink-3);
  padding-block:.95rem;
}
/* One continuous move through the property needs somewhere to read how far along it is.
   A hairline on the nav's own bottom edge does it without adding furniture to the page. */
.nav__prog{
  position:absolute; left:0; right:0; bottom:-1px; height:2px;
  background:var(--brass); transform:scaleX(0); transform-origin:left center;
  opacity:0; transition:opacity .6s var(--ease);
}
.nav.stuck .nav__prog{ opacity:.8; }

/* Agent mark + brokerage mark read as one lockup, separated by a hairline rather than a gap --
   a plain gap makes two logos look like two unrelated brands sharing a bar. The brokerage mark
   is set smaller and slightly dimmed so it reads as attribution, not as a co-headline. */
.nav__brand{ display:flex; align-items:center; gap:1rem; }
.nav__logo img{ height:34px; width:auto; transition:height .5s var(--ease); }
.nav.stuck .nav__logo img{ height:28px; }
.nav__rule{
  width:1px; height:26px; background:var(--ink-3); flex:none;
  transition:height .5s var(--ease);
}
.nav.stuck .nav__rule{ height:22px; }
/* Sized off INK, not the file box -- the supplied PNG carried transparent padding that made a
   20px box render about 15px of actual mark. broker-eg-lockup.png is the same artwork trimmed
   to its alpha bounding box, so the number below is the height you actually see. */
.nav__broker{
  height:23px; width:auto; opacity:.85; flex:none;
  transition:height .5s var(--ease), opacity .35s var(--ease);
}
.nav.stuck .nav__broker{ height:19px; }
.nav__brand:hover .nav__broker{ opacity:1; }

.nav__links{ display:flex; align-items:center; gap:2.1rem; margin-left:auto; }
.nav__links a{
  font-size:.76rem; font-weight:400; letter-spacing:.13em; text-transform:uppercase;
  color:var(--bone); opacity:.82; position:relative; padding-block:.3rem;
  transition:opacity .35s var(--ease);
}
.nav__links a::after{
  content:""; position:absolute; left:0; bottom:0; height:1px; width:100%;
  background:var(--brass); transform:scaleX(0); transform-origin:right;
  transition:transform .5s var(--ease);
}
.nav__links a:hover{ opacity:1; }
.nav__links a:hover::after{ transform:scaleX(1); transform-origin:left; }

/* ---------- primary nav dropdown --------------------------------------- */
/* Hover alone strands keyboard and touch users, so the trigger is a real <button> driving
   aria-expanded; hover, focus-within and click all resolve to the same open state. The panel
   is bridged to the trigger by padding-top on the group, not a margin -- a gap between the two
   lets the pointer cross dead space and closes the menu mid-travel. */
.nav__group{ position:relative; display:flex; align-items:center; }
.nav__sublink{
  font:inherit; background:none; border:0; cursor:pointer; padding:.3rem 0;
  display:inline-flex; align-items:center; gap:.42rem; position:relative;
  font-size:.76rem; font-weight:400; letter-spacing:.13em; text-transform:uppercase;
  color:var(--bone); opacity:.82; transition:opacity .35s var(--ease);
}
.nav__sublink::after{
  content:""; position:absolute; left:0; bottom:0; height:1px; width:100%;
  background:var(--brass); transform:scaleX(0); transform-origin:right;
  transition:transform .5s var(--ease);
}
.nav__group:not(.dismissed):hover .nav__sublink,
.nav__sublink[aria-expanded="true"]{ opacity:1; }
.nav__group:not(.dismissed):hover .nav__sublink::after,
.nav__sublink[aria-expanded="true"]::after{ transform:scaleX(1); transform-origin:left; }
.nav__chev{
  width:6px; height:6px; border-right:1px solid currentColor; border-bottom:1px solid currentColor;
  transform:translateY(-2px) rotate(45deg); transition:transform .35s var(--ease);
}
.nav__sublink[aria-expanded="true"] .nav__chev{ transform:translateY(1px) rotate(225deg); }

.nav__sub{
  position:absolute; top:100%; left:50%; margin-top:.95rem;
  min-width:190px; padding:.55rem 0;
  background:rgba(11,12,14,.94);
  backdrop-filter:blur(18px) saturate(140%);
  -webkit-backdrop-filter:blur(18px) saturate(140%);
  border:1px solid var(--ink-3);
  display:flex; flex-direction:column;
  opacity:0; visibility:hidden;
  transform:translate(-50%,-6px);
  transition:opacity .3s var(--ease), transform .3s var(--ease), visibility .3s;
}
/* The bridge: an invisible strip spanning the margin so the pointer never leaves the group. */
.nav__sub::before{ content:""; position:absolute; left:0; right:0; top:-.95rem; height:.95rem; }
.nav__group:not(.dismissed):hover .nav__sub,
.nav__group:not(.dismissed):focus-within .nav__sub,
.nav__sub.open{ opacity:1; visibility:visible; transform:translate(-50%,0); }
.nav__sub a{
  padding:.62rem 1.35rem; white-space:nowrap;
  font-size:.74rem; letter-spacing:.13em; text-transform:uppercase;
  color:var(--bone); opacity:.74;
  transition:opacity .3s var(--ease), background .3s var(--ease), padding-left .3s var(--ease);
}
.nav__sub a::after{ display:none; }
.nav__sub a:hover,
.nav__sub a:focus-visible{ opacity:1; background:rgba(181,139,82,.1); padding-left:1.6rem; }

.nav__cta{ display:flex; align-items:center; gap:1.4rem; }
.nav__tel{
  font-size:.78rem; letter-spacing:.09em; color:var(--mute);
  white-space:nowrap;                 /* wrapped to "(480) 300-" / "2829" on a 390px phone */
  transition:color .35s var(--ease);
}
.nav__tel:hover{ color:var(--bone); }

.nav__burger{
  display:none; margin-left:auto; width:38px; height:38px;
  background:none; border:0; cursor:pointer; padding:0;
  flex-direction:column; justify-content:center; gap:6px;
}
.nav__burger span{
  display:block; height:1px; width:22px; margin-inline:auto; background:var(--bone);
  transition:transform .4s var(--ease), opacity .3s var(--ease);
}
.nav.open .nav__burger span:first-child{ transform:translateY(3.5px) rotate(45deg); }
.nav.open .nav__burger span:last-child{ transform:translateY(-3.5px) rotate(-45deg); }

/* ---------- hero -------------------------------------------------------- */

/* Anchored to the top, not the bottom. Bottom-anchoring dropped the headline straight onto the
   lit house and its glowing windows -- the busiest, brightest region of the photograph -- so the
   type had to fight the image instead of sitting in it. Held up here, the headline lands in the
   sky-and-ridgeline band and the house reads as the floor of the composition. */
.hero{
  position:relative; min-height:100svh;
  display:flex; align-items:flex-start;
  padding:clamp(6rem,13vh,9.5rem) max(4vw,1.25rem) clamp(4rem,9vh,7rem);
  overflow:hidden;
}
.hero__media{ position:absolute; inset:-6% 0; z-index:0; will-change:transform; }
.hero__media img{ width:100%; height:100%; object-fit:cover; object-position:center 55%; }
/* Re-weighted for top-anchored type. The old scrim was darkest at the bottom and thinnest at 62%
   -- which is exactly the band the lit windows occupy -- so once the copy moved up, the subhead
   and buttons landed on the brightest pixels in the photograph and stopped being readable. The
   horizontal wash does the protecting now: the type is all left-aligned, so darkening the left
   column keeps it legible while leaving the house and pool on the right at full glow. */
.hero__scrim{
  position:absolute; inset:0; z-index:1;
  background:
    linear-gradient(to right, rgba(11,12,14,.86) 0%, rgba(11,12,14,.74) 34%, rgba(11,12,14,.46) 62%, rgba(11,12,14,.16) 80%, transparent 92%),
    linear-gradient(to bottom, rgba(11,12,14,.72) 0%, rgba(11,12,14,.30) 34%, rgba(11,12,14,.10) 60%, rgba(11,12,14,.55) 100%);
}
/* Seam dissolve. The photograph used to stop dead on the ticker's 1px top border — a cut, and
   the first thing that told you this was a stack of sections rather than one continuous move.
   Fading its last band into the ticker's own surface means the eye travels sky → house → band
   without ever meeting an edge: the camera tilts down out of the shot instead of cutting. */
.hero::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:var(--seam); z-index:1;
  background:linear-gradient(to bottom,
    rgba(20,22,26,0) 0%, rgba(20,22,26,.45) 52%, rgba(20,22,26,.85) 82%, var(--ink-2) 100%);
  pointer-events:none;
}
.hero__inner{ position:relative; z-index:2; width:var(--shell); margin-inline:auto; }
.hero__title{
  font-size:clamp(2.7rem,7.4vw,7.2rem);
  margin:0 0 1.6rem; max-width:16ch;
}
/* the italic's right sidebearing swallows the word space — "high-endArizona" without this */
.hero__title em{ font-style:italic; color:var(--brass-lt); margin-right:.11em; }
.hero__title .line{ display:block; overflow:hidden; }
.hero__title .line > span{
  display:block; transform:translateY(105%);
  transition:transform .8s var(--slow); transition-delay:var(--d,0ms);
}
.hero.lit .hero__title .line > span{ transform:none; }
/* --mute is a secondary-text colour tuned for solid dark panels; over the photograph it measured
   2.0:1 against the lit windows, well under AA. Bone plus a soft shadow keeps the line quiet
   without making it a legibility problem. */
.hero__sub{
  font-size:.86rem; letter-spacing:.12em; text-transform:uppercase;
  color:var(--bone); margin-bottom:2.4rem;
  text-shadow:0 1px 14px rgba(11,12,14,.9), 0 1px 3px rgba(11,12,14,.75);
}
.hero__actions{ display:flex; flex-wrap:wrap; gap:1rem; }

.hero__cue{
  position:absolute; right:max(4vw,1.25rem); bottom:clamp(4rem,9vh,7rem); z-index:2;
  display:flex; align-items:center; gap:.8rem;
  font-size:.66rem; letter-spacing:.28em; text-transform:uppercase; color:var(--mute);
}
.hero__cue span{
  display:block; width:1px; height:52px;
  background:linear-gradient(to bottom, transparent, var(--brass));
  animation:cue 2.6s var(--ease) infinite;
}
@keyframes cue{ 0%,100%{ transform:scaleY(.45); opacity:.4; } 50%{ transform:scaleY(1); opacity:1; } }

/* ---------- ticker ------------------------------------------------------ */

/* Both hairline borders are gone. They were the two hardest lines on the page: one closed the
   hero photograph, the other opened the stats. The band now arrives out of the hero's dissolve
   and leaves through its own, so hero → ticker → stats is a single uninterrupted surface. */
.ticker{
  background:linear-gradient(to bottom, var(--ink-2) 0%, var(--ink-2) 58%, var(--ink) 100%);
  overflow:hidden; padding-block:1.15rem 2.2rem;
}
.ticker__row{
  display:flex; gap:2.4rem; width:max-content;
  animation:slide 48s linear infinite;
  font-family:var(--f-display); font-size:1.05rem; letter-spacing:.02em;
  color:var(--bone); opacity:.62; white-space:nowrap;
}
.ticker__row i{ color:var(--brass); font-style:normal; }
@keyframes slide{ to{ transform:translateX(-50%); } }

/* ---------- stats ------------------------------------------------------- */

.stats{ width:var(--shell); margin-inline:auto; padding:var(--section) 0; }
.stats__grid{
  display:grid; grid-template-columns:repeat(4,1fr);
  gap:1px; background:var(--ink-3);
  border:1px solid var(--ink-3);
}
.stat{ background:var(--ink); padding:clamp(1.9rem,3.2vw,3rem); }
.stat__num{
  display:block;
  font-family:var(--f-display); font-weight:300;
  font-size:clamp(2.4rem,4.4vw,3.9rem); line-height:1;
  letter-spacing:-.03em; color:var(--bone);
  font-variant-numeric:tabular-nums;
  margin-bottom:1rem;
}
/* A one-character suffix (M, %) rides at full size. A written-out one — "Million",
   "Less Days" — is a word, not a digit: at 3.9rem it runs straight out of a quarter-width
   cell, so it drops to a size that fits and sits on its own line under the figure. */
.stat__suf{
  display:block; font-style:normal;
  font-size:.34em; line-height:1.15; letter-spacing:-.01em;
  margin-top:.35em;
}
.stat__label{
  display:block; font-size:.76rem; line-height:1.6;
  letter-spacing:.1em; text-transform:uppercase; color:var(--mute); max-width:26ch;
}

/* ---------- about ------------------------------------------------------- */

.about{
  width:var(--shell); margin-inline:auto;
  display:grid; grid-template-columns:.85fr 1fr; gap:clamp(3rem,7vw,7rem);
  padding-bottom:var(--section);
  align-items:start;
}
.about__sticky{ position:sticky; top:16vh; }
.portrait{ margin:0; position:relative; }
.portrait__room{
  width:100%; aspect-ratio:4/5; object-fit:cover;
  border-radius:var(--r); filter:saturate(.9) contrast(1.03);
}
/* Sized and placed against the corrected 4:5 box. While the frame was wrongly rendering at twice
   its designed height these values looked fine; once it collapsed to the right shape a 46% circle
   sitting 12% up covered the seating area and pushed the caption into a three-line wrap. */
.portrait__cut{
  position:absolute; right:-7%; bottom:21%;
  width:39%; border-radius:50%;
  background:var(--bone);
  box-shadow:0 40px 80px -30px rgba(0,0,0,.85), 0 0 0 1px rgba(244,241,236,.1);
}
/* The scrim must span the FULL width. Stopping it short of the portrait cut-out drew a hard
   vertical seam straight down the middle of the photograph; the text is held clear of the
   circle with padding instead. */
.portrait figcaption{
  position:absolute; left:0; right:0; bottom:0;
  padding:2.2rem 1.5rem 1.4rem;
  padding-right:34%;
  background:linear-gradient(to top, rgba(11,12,14,.94), rgba(11,12,14,.55) 55%, transparent);
}
.portrait figcaption strong{
  display:block; font-family:var(--f-display); font-size:1.35rem; font-weight:300; letter-spacing:-.02em;
}
.portrait figcaption span{
  display:block; font-size:.7rem; letter-spacing:.16em; text-transform:uppercase; color:var(--brass); margin-top:.35rem;
}

.about__copy h2{ margin-bottom:2rem; }
.about__copy .lede{
  font-family:var(--f-display); font-size:clamp(1.2rem,1.65vw,1.5rem);
  line-height:1.5; color:var(--bone); letter-spacing:-.01em;
}
.about__copy p{ color:var(--mute); max-width:60ch; }
.about__copy blockquote{
  margin:2.6rem 0; padding-left:1.6rem;
  border-left:1px solid var(--brass);
  font-family:var(--f-display); font-size:clamp(1.15rem,1.5vw,1.4rem);
  line-height:1.45; color:var(--bone); font-style:italic;
}
.chips{ list-style:none; display:flex; flex-wrap:wrap; gap:.55rem; padding:0; margin:0 0 2.4rem; }
.chips li{
  border:1px solid var(--ink-3); border-radius:100px;
  padding:.45rem 1rem; font-size:.72rem; letter-spacing:.09em;
  text-transform:uppercase; color:var(--mute);
}

/* ---------- communities rail ------------------------------------------- */

.areas{ padding-bottom:var(--section); overflow:hidden; }
/* The 900px cap used to be on the block itself, which centred the whole head — so this was the
   only single-column section heading on the page that did not begin on the shell's left edge.
   Reading down the page the eye line jumped 80px → 350px → 80px, and the head lined up with
   nothing below it either, since the cards start at the 4vw gutter. The cap belongs on the
   measure of the text, not on the position of the block. */
.areas__head{ width:var(--shell); margin:0 auto clamp(3rem,6vh,4.5rem); }
.areas__head > *{ max-width:900px; }
.areas__note{ color:var(--mute); max-width:52ch; margin-top:1.6rem; }

/* proximity, not mandatory: mandatory snaps back from any resting position the visitor chooses,
   which reads as the page arguing with them. overscroll-behavior-x keeps a horizontal fling from
   escaping into browser back-navigation. */
.rail{
  overflow-x:auto; scrollbar-width:none;
  scroll-snap-type:x proximity; overscroll-behavior-x:contain;
  -webkit-overflow-scrolling:touch;
  /* Without this the section loads already scrolled 64px in. scroll-snap-align:start measures
     against the SCROLLPORT edge, not the track's leading padding, so the first card's snap
     position was 64px and the browser jumped there on load — the heading sat on the shell
     margin while the card beneath it was sliced off by the viewport. Matching the scroll
     padding to the track padding puts the first card's snap position at zero. */
  scroll-padding-inline-start:calc((100% - var(--shell)) / 2);
}
.rail::-webkit-scrollbar{ display:none; }
.rail__track{
  display:flex; gap:1.25rem;
  /* The gutter is the shell's own margin, not a raw 4vw. Above ~1565px the shell stops growing
     and centres itself, so a 4vw gutter drifted 16px inside the heading above it and the first
     card no longer began on the page's left edge. */
  padding-inline:calc((100% - var(--shell)) / 2);
  width:max-content;
}
/* The row arrives left-to-right, so entering this section reads as walking past the cards
   rather than eight tiles appearing at once. Opacity only, deliberately: .card already owns
   its transform on hover, and two rules fighting over transform is a flicker on mouse-out.
   The stagger is CSS rather than the shared observer because cards five to eight sit outside
   the viewport horizontally — an IntersectionObserver would never fire for them and they
   would stay at opacity 0 forever. The rail is what gets observed; the cards follow it. */
.rail .card{ opacity:0; transition:opacity .9s var(--slow); }
.rail.in .card{ opacity:1; }
.rail.in .card:nth-child(2){ transition-delay:80ms; }
.rail.in .card:nth-child(3){ transition-delay:160ms; }
.rail.in .card:nth-child(4){ transition-delay:240ms; }
.rail.in .card:nth-child(5){ transition-delay:320ms; }
.rail.in .card:nth-child(6){ transition-delay:400ms; }
.rail.in .card:nth-child(7){ transition-delay:460ms; }
.rail.in .card:nth-child(8){ transition-delay:520ms; }

.card{
  flex:0 0 clamp(260px,25vw,360px);
  scroll-snap-align:start;
  position:relative; display:block;
  border:1px solid var(--ink-3); border-radius:var(--r);
  overflow:hidden; background:var(--ink-2);
  transition:border-color .55s var(--ease), transform .55s var(--ease);
}
.card:hover{ border-color:rgba(181,139,82,.5); transform:translateY(-6px); }
.card__img{ overflow:hidden; aspect-ratio:3/4; background:var(--ink-3); }
.card__img img{
  width:100%; height:100%; object-fit:cover;
  transition:transform 1.2s var(--slow), filter .6s var(--ease);
  filter:saturate(.88) contrast(1.04);
}
.card:hover .card__img img{ transform:scale(1.06); filter:saturate(1) contrast(1.04); }
.card__meta{
  position:absolute; inset:auto 0 0 0; padding:1.5rem;
  background:linear-gradient(to top, rgba(11,12,14,.95) 30%, rgba(11,12,14,.65) 65%, transparent);
}
.card__idx{
  display:block; font-size:.68rem; letter-spacing:.22em; color:var(--brass); margin-bottom:.6rem;
}
.card__meta h3{ margin-bottom:.5rem; }
.card__meta p{ font-size:.82rem; color:var(--mute); margin:0; line-height:1.55; }
.card--cta{
  background:var(--ink-2); display:flex; align-items:flex-end;
  border-color:rgba(181,139,82,.35);
}
.card--cta .card__meta{ position:static; background:none; padding:1.8rem; }
.card--cta .card__meta p{ margin-bottom:1.6rem; }

.rail__hint{
  width:var(--shell); margin:2.6rem auto 0;
  display:flex; align-items:center; gap:1.5rem;
}
.rail__bar{ display:block; height:1px; background:var(--ink-3); position:relative; flex:1; }
.rail__nav{ display:flex; gap:.5rem; flex:0 0 auto; }
.rail__btn{
  width:2.75rem; height:2.75rem; border-radius:50%;
  border:1px solid var(--ink-3); background:transparent; color:var(--bone);
  font-size:1rem; line-height:1; cursor:pointer;
  transition:border-color .3s var(--slow), background .3s var(--slow), opacity .3s var(--slow);
}
.rail__btn:hover:not(:disabled){ border-color:var(--brass); background:rgba(196,157,95,.12); }
.rail__btn:disabled{ opacity:.3; cursor:default; }
.rail__btn:focus-visible{ outline:2px solid var(--brass); outline-offset:3px; }
/* grab cursor only while a drag is genuinely available (pointer, not touch) */
@media (hover:hover){ .rail{ cursor:grab; } .rail.is-dragging{ cursor:grabbing; } }
.rail.is-dragging{ scroll-snap-type:none; user-select:none; }
.rail__bar i{
  position:absolute; inset:0 auto 0 0; display:block;
  height:1px; width:22%; background:var(--brass);
  transition:transform .12s linear;
}

/* ---------- buy / sell panels ------------------------------------------ */

.work{ width:var(--shell); margin-inline:auto; display:grid; gap:clamp(5rem,10vh,9rem); padding-bottom:var(--section); }
.panel{
  display:grid; grid-template-columns:1fr 1fr; gap:clamp(2.5rem,5vw,5rem);
  align-items:center;
}
.panel--flip .panel__media{ order:2; }
/* The parallax used to be bound to this frame, so the whole picture — rounded corners and all —
   slid up and down against the text column beside it and the two halves of the panel drifted
   out of alignment as you scrolled. The frame is fixed now and the photograph moves inside it,
   which is what a camera pass actually looks like: the opening stays put, the view through it
   changes. height:126% gives the drift room to travel without ever exposing an edge. */
.panel__media{ overflow:hidden; border-radius:var(--r); aspect-ratio:4/3; position:relative; }
.panel__media img{
  position:absolute; inset:-13% 0 auto 0;
  width:100%; height:126%; object-fit:cover;
  filter:saturate(.92) contrast(1.03);
  will-change:transform;
}
.panel__body h2{ margin-bottom:1.6rem; }
.panel__body > p{ color:var(--mute); max-width:52ch; }

.specs{ margin:2.4rem 0; padding:0; }
.specs > div{
  padding:1.15rem 0; border-top:1px solid var(--ink-3);
  display:grid; grid-template-columns:1fr; gap:.35rem;
}
.specs > div:last-child{ border-bottom:1px solid var(--ink-3); }
.specs dt{
  font-family:var(--f-display); font-size:1.05rem; letter-spacing:-.01em; color:var(--bone);
}
.specs dd{ margin:0; font-size:.87rem; color:var(--mute); line-height:1.6; }

/* ---------- testimonials ------------------------------------------------ */

.proof{ width:var(--shell); margin-inline:auto; padding-bottom:var(--section); }
.proof__head{ margin-bottom:clamp(3rem,6vh,4.5rem); }
.proof__note{ margin:1.1rem 0 0; color:var(--mute); font-size:.95rem; max-width:36ch; }
.proof__grid{ display:grid; grid-template-columns:repeat(2,1fr); gap:1px; background:var(--ink-3); border:1px solid var(--ink-3); }
.quote{
  margin:0; background:var(--ink); padding:clamp(1.4rem,2.2vw,2rem) clamp(1.4rem,2.2vw,2rem) clamp(2rem,3.4vw,3.2rem);
  display:flex; flex-direction:column; gap:1.5rem;
}

/* ---- video facade ---- */
.vt{
  position:relative; aspect-ratio:16/9; overflow:hidden;
  border-radius:var(--r); background:var(--ink-2); isolation:isolate;
}
.vt__poster{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover; display:block;
  filter:saturate(.94) contrast(1.02);
  transition:transform 1.1s var(--slow), filter .5s var(--ease);
}
/* Scrim keeps the play control legible over a bright kitchen or a white-walled room. */
.vt::after{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:1;
  background:linear-gradient(to top, rgba(11,12,14,.82) 0%, rgba(11,12,14,.34) 24%, rgba(11,12,14,0) 56%);
  transition:opacity .45s var(--ease);
}
/* The control sits bottom-left rather than dead centre: every one of these films is a
   centred talking head, and a centred play button lands squarely on the client's face. */
.vt__play{
  position:absolute; inset:0; z-index:2; width:100%; height:100%;
  display:flex; align-items:flex-end; justify-content:flex-start; gap:.95rem;
  background:none; border:0; padding:0 0 1.15rem 1.15rem; cursor:pointer; color:var(--bone);
  font-family:var(--f-ui); font-size:.72rem; letter-spacing:.16em; text-transform:uppercase;
  text-align:left;
}
.vt__glyph{
  width:58px; height:58px; border-radius:50%; flex:none;
  border:1px solid rgba(244,241,236,.55); background:rgba(11,12,14,.28);
  backdrop-filter:blur(2px); -webkit-backdrop-filter:blur(2px);
  display:grid; place-items:center;
  transition:background .35s var(--ease), border-color .35s var(--ease), transform .45s var(--slow);
}
.vt__glyph::before{
  content:""; width:0; height:0; margin-left:4px;                 /* optical centring of a triangle */
  border-left:13px solid currentColor;
  border-top:8px solid transparent; border-bottom:8px solid transparent;
  transition:border-left-color .35s var(--ease);
}
.vt__label{
  opacity:.92; text-shadow:0 1px 12px rgba(0,0,0,.75);
  padding-bottom:.35rem; max-width:14ch; line-height:1.45;
}
.vt__time{
  position:absolute; z-index:2; right:.9rem; bottom:.85rem;
  font-size:.68rem; letter-spacing:.12em; color:var(--bone);
  background:rgba(11,12,14,.6); border:1px solid rgba(244,241,236,.14);
  border-radius:var(--r); padding:.24rem .5rem; font-variant-numeric:tabular-nums;
}
.vt__play:hover .vt__glyph,
.vt__play:focus-visible .vt__glyph{
  background:var(--brass); border-color:var(--brass); color:#0b0c0e; transform:scale(1.06);
}
.vt:hover .vt__poster{ transform:scale(1.035); }
.vt.is-playing::after,
.vt.is-playing .vt__time{ opacity:0; }
.vt iframe{ position:absolute; inset:0; width:100%; height:100%; border:0; z-index:3; }

.quote__stars{ color:var(--brass); letter-spacing:.35em; font-size:.85rem; }
.quote blockquote{
  margin:0; flex:1;
  font-family:var(--f-display); font-size:clamp(1.05rem,1.35vw,1.28rem);
  line-height:1.55; letter-spacing:-.008em; color:var(--bone);
}
.quote figcaption{
  display:flex; flex-direction:column; gap:.25rem;
  padding-top:1.35rem; border-top:1px solid var(--ink-3);
}
.quote figcaption span{ font-size:.72rem; letter-spacing:.16em; text-transform:uppercase; color:var(--mute); }
.quote figcaption strong{
  font-family:var(--f-display); font-size:1.15rem; font-weight:400;
  letter-spacing:-.01em; color:var(--bone);
}

@media (prefers-reduced-motion:reduce){
  .vt__poster, .vt__glyph{ transition:none; }
  .vt:hover .vt__poster{ transform:none; }
}

/* ---------- tools grid -------------------------------------------------- */

.tools{
  width:var(--shell); margin-inline:auto;
  display:grid; grid-template-columns:repeat(3,1fr); gap:1px;
  background:var(--ink-3); border:1px solid var(--ink-3);
  /* no bottom margin: the contact photograph supplies the gap through its own top dissolve.
     Stacking both produced a ~20rem void here, twice every other gap on the page. */
  margin-bottom:0;
}
.tool{
  background:var(--ink); padding:clamp(1.9rem,3vw,2.8rem);
  display:flex; flex-direction:column; gap:.7rem;
  transition:background .5s var(--ease);
}
.tool:hover{ background:var(--ink-2); }
.tool__idx{ font-size:.68rem; letter-spacing:.22em; color:var(--brass); }
.tool p{ font-size:.86rem; color:var(--mute); margin:0; flex:1; }
.tool .link-arrow{ margin-top:1.1rem; align-self:flex-start; }

/* ---------- contact ----------------------------------------------------- */

/* The last room. It used to begin on a hard horizontal edge — black page, then abruptly a lit
   night terrace — and end on the footer's border, so the page's two photographs were also its
   two most obvious joins. Both edges now dissolve: the ground melts into the photograph on the
   way in and back out into the footer's surface on the way out. Padding is keyed to the seam
   depth so the copy always starts below the wash rather than inside it. */
.contact{
  position:relative; overflow:hidden;
  padding-block:calc(var(--seam) + 1.5rem);
}
.contact::before{
  content:""; position:absolute; inset:0 0 auto 0; height:var(--seam); z-index:1;
  background:linear-gradient(to bottom,
    var(--ink) 0%, rgba(11,12,14,.82) 30%, rgba(11,12,14,.40) 66%, transparent 100%);
  pointer-events:none;
}
.contact::after{
  content:""; position:absolute; inset:auto 0 0 0; height:calc(var(--seam) * .8); z-index:1;
  background:linear-gradient(to bottom, transparent, rgba(20,22,26,.7) 62%, var(--ink-2) 100%);
  pointer-events:none;
}
.contact__media{ position:absolute; inset:-8% 0; z-index:0; will-change:transform; }
.contact__media img{ width:100%; height:100%; object-fit:cover; }
.contact__scrim{
  position:absolute; inset:0; z-index:1;
  background:linear-gradient(105deg, rgba(11,12,14,.93) 0%, rgba(11,12,14,.74) 45%, rgba(11,12,14,.34) 100%);
}
.contact__inner{
  position:relative; z-index:2; width:var(--shell); margin-inline:auto;
  display:grid; grid-template-columns:1fr .85fr; gap:clamp(3rem,6vw,6rem); align-items:start;
}
.contact__pitch h2{ margin-bottom:1.6rem; }
.contact__pitch > p{ color:var(--mute); max-width:44ch; }

.contact__details{ list-style:none; padding:0; margin:2.8rem 0 2rem; }
.contact__details li{
  display:grid; grid-template-columns:5.5rem 1fr; gap:1rem; align-items:baseline;
  padding:1rem 0; border-top:1px solid var(--ink-3);
}
.contact__details li:last-child{ border-bottom:1px solid var(--ink-3); }
.contact__details span{ font-size:.68rem; letter-spacing:.2em; text-transform:uppercase; color:var(--brass); }
.contact__details a,.contact__details em{
  font-family:var(--f-display); font-size:1.08rem; font-style:normal; letter-spacing:-.01em;
  transition:color .35s var(--ease);
}
.contact__details a:hover{ color:var(--brass-lt); }
.contact__social{ display:flex; gap:1.6rem; }
.contact__social a{
  font-size:.72rem; letter-spacing:.16em; text-transform:uppercase; color:var(--mute);
  padding-bottom:.3rem; border-bottom:1px solid var(--ink-3);
  transition:color .35s var(--ease), border-color .35s var(--ease);
}
.contact__social a:hover{ color:var(--bone); border-color:var(--brass); }

.form{
  background:rgba(20,22,26,.72);
  backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px);
  border:1px solid var(--ink-3); border-radius:var(--r);
  padding:clamp(1.8rem,3vw,2.6rem);
}
.form__fields{ display:flex; flex-direction:column; gap:1.1rem; }

/* Confirmation replaces the fields in place rather than scrolling somewhere new -- the reader
   is already looking here, and a swap keeps the answer where the question was. */
.form__done{ display:none; flex-direction:column; align-items:flex-start; justify-content:center; gap:.9rem; }
.form.is-sent .form__fields{ display:none; }
.form.is-sent .form__done{ display:flex; }
.form__done-mark{
  width:44px; height:44px; border-radius:50%; flex:none;
  border:1px solid var(--brass); position:relative;
}
.form__done-mark::after{
  content:""; position:absolute; left:15px; top:13px; width:11px; height:19px;
  border-right:1px solid var(--brass); border-bottom:1px solid var(--brass);
  transform:rotate(45deg);
}
.form__done-title{ font-size:clamp(1.15rem,2vw,1.45rem); font-weight:400; margin:0; line-height:1.3; }
.form__done-body{ font-size:.92rem; line-height:1.7; color:var(--mute); margin:0; }
.form__done-body a{ color:var(--brass); }
.form__done-note{
  font-size:.74rem; line-height:1.65; color:var(--mute-d); margin:.2rem 0 0;
  padding:.85rem 1rem; border-left:2px solid var(--brass);
  background:rgba(181,139,82,.07);
}
.form__done-note strong{ color:var(--mute); font-weight:500; }
.form__done-reset{
  font:inherit; background:none; border:0; cursor:pointer; padding:.2rem 0; margin-top:.2rem;
  font-size:.75rem; letter-spacing:.1em; text-transform:uppercase; color:var(--mute);
  border-bottom:1px solid var(--ink-3); transition:color .35s var(--ease), border-color .35s var(--ease);
}
.form__done-reset:hover{ color:var(--brass); border-bottom-color:var(--brass); }

.form__error{
  display:none; margin:0; font-size:.8rem; line-height:1.6; color:#e5a3a3;
  padding:.75rem .95rem; border-left:2px solid #b56a6a; background:rgba(181,106,106,.09);
}
.form.is-error .form__error{ display:block; }
.form__error a{ color:#e5a3a3; border-bottom:1px solid rgba(229,163,163,.4); }
.form__row{ display:grid; grid-template-columns:1fr 1fr; gap:1.1rem; }
.form label{
  display:flex; flex-direction:column; gap:.5rem;
  font-size:.68rem; letter-spacing:.18em; text-transform:uppercase; color:var(--mute);
}
.form input,.form textarea{
  font-family:var(--f-ui); font-size:.95rem; font-weight:300; color:var(--bone);
  background:transparent; border:0; border-bottom:1px solid var(--ink-3);
  padding:.7rem 0; border-radius:0; letter-spacing:normal; text-transform:none;
  transition:border-color .4s var(--ease);
}
.form textarea{ resize:vertical; }
.form input:focus,.form textarea:focus{ outline:none; border-bottom-color:var(--brass); }
.form__consent{ font-size:.72rem; line-height:1.6; color:var(--mute-d); margin:.4rem 0 0; }
.form__consent a{ color:var(--mute); border-bottom:1px solid var(--ink-3); }
.form .btn{ margin-top:.4rem; }
.form__alt{ font-size:.75rem; letter-spacing:.1em; color:var(--mute); text-align:center; }
.form__alt:hover{ color:var(--brass); }

/* ---------- footer ------------------------------------------------------ */

/* No top border: the contact photograph already arrives here through a dissolve, and a hairline
   across it would put back the one edge that dissolve exists to remove. */
.foot{ background:var(--ink-2); }
.foot__top{
  width:var(--shell); margin-inline:auto;
  display:grid; grid-template-columns:1.5fr 1fr 1fr .8fr 1fr; gap:clamp(1.6rem,3vw,3.2rem);
  padding:clamp(4rem,8vh,6rem) 0 clamp(3rem,5vh,4rem);
}
.foot__brand img{ height:40px; width:auto; margin-bottom:1.6rem; }
.foot__brand p{ font-size:.87rem; color:var(--mute); max-width:38ch; }
.foot__brokerage{ color:var(--brass) !important; font-size:.78rem !important; letter-spacing:.1em; text-transform:uppercase; }
.foot__col{ display:flex; flex-direction:column; gap:.75rem; }
.foot__col h3{
  margin:0 0 .6rem; font-family:var(--f-ui);
  font-size:.68rem; font-weight:600; letter-spacing:.2em; text-transform:uppercase; color:var(--bone);
}
.foot__col a,.foot__col span{ font-size:.87rem; color:var(--mute); transition:color .35s var(--ease); }
.foot__col a:hover{ color:var(--brass); }

.foot__disclaimer{
  width:var(--shell); margin-inline:auto;
  font-size:.72rem; line-height:1.7; color:var(--mute-d);
  padding-bottom:2rem; border-bottom:1px solid var(--ink-3); max-width:none;
}
.foot__bar{
  width:var(--shell); margin-inline:auto;
  display:flex; justify-content:space-between; align-items:center; gap:1.5rem; flex-wrap:wrap;
  padding-block:1.8rem; font-size:.75rem; color:var(--mute-d);
}
.foot__bar nav{ display:flex; gap:1.6rem; }
.foot__bar a:hover{ color:var(--bone); }

/* ---------- responsive -------------------------------------------------- */

@media (max-width:1080px){
  .stats__grid{ grid-template-columns:repeat(2,1fr); }
  .about{ grid-template-columns:1fr; }
  .about__sticky{ position:static; }
  .portrait__room{ aspect-ratio:16/10; }
  .portrait__cut{ width:32%; right:2%; }
  .tools{ grid-template-columns:repeat(2,1fr); }
  .foot__top{ grid-template-columns:1fr 1fr; }
}

@media (max-width:860px){
  /* The open sheet must be OPAQUE. It was see-through on a phone, but only after
     scrolling, and the cause is not the background -- it is `backdrop-filter` on
     `.nav.stuck`. A filtered ancestor becomes the containing block for its own
     position:fixed children, so once the bar went sticky this panel's `inset:0`
     stopped meaning "the viewport" and started meaning "the nav bar": measured at
     390x797 at the top of the page and 390x21 after a scroll. The background was
     painting the whole time -- into a 21px strip, with the links spilling out over
     the page below it. So the nav drops its filter while the menu is open, which
     hands the panel the viewport back, and the panel no longer relies on a
     translucent surface it cannot guarantee. */
  .nav.open,
  .nav.open.stuck{ backdrop-filter:none; -webkit-backdrop-filter:none; }

  .nav__links{
    position:fixed; inset:0; z-index:-1;
    width:100vw; min-height:100dvh;
    flex-direction:column; justify-content:center; align-items:center; gap:2rem;
    /* Fully opaque, and no filter of its own: iOS Safari renders a backdrop-filter
       nested inside another one unreliably, and there is nothing to blur behind an
       opaque sheet anyway. */
    background:var(--ink);
    /* Equal top and bottom: the top pad exists to clear the fixed bar, but pairing it
       with a smaller bottom pad and justify-content:center lands the list off-centre. */
    padding-block:calc(var(--nav-h) + 1rem);
    overflow-y:auto; -webkit-overflow-scrolling:touch;
    opacity:0; pointer-events:none; transition:opacity .45s var(--ease);
  }
  .nav.open .nav__links{ opacity:1; pointer-events:auto; z-index:1; }

  /* Now that the sheet really does fill the viewport, it covers its own siblings --
     including the button that closes it. The logo and the burger have to sit above it
     or the menu becomes a trap. (Invisible while the panel was 21px tall, which is why
     it only shows up once the sheet is fixed.) */
  .nav.open .nav__brand,
  .nav.open .nav__cta,
  .nav.open .nav__burger{ position:relative; z-index:2; }

  .nav__links a{ font-size:1.05rem; }
  .nav__cta .btn{ display:none; }
  .nav__cta{ margin-left:auto; }
  .nav__burger{ display:flex; margin-left:1rem; }

  /* In the fullscreen sheet a floating dropdown has nothing to float against, so Resources
     becomes an inline accordion that pushes the sheet rather than covering it. Hover is
     meaningless on touch -- only the explicit .open class drives it here. */
  .nav__group{ flex-direction:column; align-items:center; gap:0; }
  .nav__sublink{ font-size:1.05rem; letter-spacing:.13em; padding:.3rem 0; }
  .nav__sub{
    position:static; transform:none; margin-top:0; min-width:0; padding:0;
    background:none; border:0; backdrop-filter:none; -webkit-backdrop-filter:none;
    align-items:center; overflow:hidden;
    max-height:0; opacity:0; visibility:visible;
    transition:max-height .4s var(--ease), opacity .3s var(--ease), margin-top .4s var(--ease);
  }
  .nav__sub::before{ display:none; }
  .nav__group:hover .nav__sub,
  .nav__group:focus-within .nav__sub:not(.open){ max-height:0; opacity:0; margin-top:0; }
  .nav__sub.open,
  .nav__group:focus-within .nav__sub.open{ max-height:260px; opacity:1; margin-top:1.1rem; }
  .nav__sub a{
    padding:.5rem 0; font-size:.9rem; opacity:.66;
    color:var(--mute); background:none;
  }
  .nav__sub a:hover,
  .nav__sub a:focus-visible{ background:none; padding-left:0; opacity:1; color:var(--bone); }

  .hero{ min-height:92svh; padding-bottom:max(4rem, env(safe-area-inset-bottom) + 3rem); }
  .hero__cue{ display:none; }
  .panel,.panel--flip .panel__media{ grid-template-columns:1fr; order:0; }
  .panel{ gap:2rem; }
  .proof__grid{ grid-template-columns:1fr; }
  .contact__inner{ grid-template-columns:1fr; }
  .foot__top{ grid-template-columns:1fr; }
  .foot__disclaimer,.foot__bar{ padding-bottom:1.4rem; }
}

@media (max-width:560px){
  .nav__tel{ display:none; }          /* the burger + hero CTA already cover the call path */
  /* Both marks stay on a phone -- brokerage attribution is not a nice-to-have -- but the
     lockup tightens so it can't collide with the burger at 360px. */
  .nav__brand{ gap:.7rem; }
  .nav__logo img,
  .nav.stuck .nav__logo img{ height:26px; }
  .nav__rule,
  .nav.stuck .nav__rule{ height:18px; }
  .nav__broker,
  .nav.stuck .nav__broker{ height:16px; }
  .vt__glyph{ width:50px; height:50px; }
  .vt__label{ font-size:.66rem; max-width:12ch; }
  .stats__grid{ grid-template-columns:1fr; }
  .tools{ grid-template-columns:1fr; }
  .form__row{ grid-template-columns:1fr; }
  .contact__details li{ grid-template-columns:1fr; gap:.2rem; }
}

@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{ animation-duration:.01ms !important; animation-iteration-count:1 !important;
                        transition-duration:.01ms !important; }
  .reveal{ opacity:1; transform:none; }
  .reveal--media{ opacity:1; clip-path:none; }
  .section-label.reveal::before{ transform:none; }
  .rail .card{ opacity:1; }
  .nav__prog{ display:none; }
  .hero__title .line > span{ transform:none; }
  .ticker__row{ animation:none; }
}

/* ========================================================================
   RESOURCES PAGE (resources.html)
   A secondary page, so it borrows every primitive above -- .btn, .reveal,
   .section-label, .card, .vt, .foot -- and only adds the layouts that do
   not exist on the homepage. Nothing here is loaded conditionally; it is a
   few kilobytes and one stylesheet keeps the two pages honest with
   each other.
   ===================================================================== */

/* The nav is solid from the first pixel here, so the page needs to start below it rather
   than under it -- there is no hero for the bar to float over. */
.phead{
  padding:calc(clamp(7rem,14vh,9rem) + 1.5rem) 0 var(--section);
  border-bottom:1px solid var(--ink-3);
}
.phead__inner{ width:var(--shell); margin-inline:auto; max-width:1100px; }

.crumb{
  display:flex; align-items:center; gap:.75rem; margin-bottom:2.2rem;
  font-size:.7rem; letter-spacing:.2em; text-transform:uppercase; color:var(--mute-d);
}
.crumb a{ color:var(--mute); transition:color .35s var(--ease); }
.crumb a:hover{ color:var(--brass); }
.crumb span[aria-hidden]{ opacity:.4; }
.crumb [aria-current]{ color:var(--brass); }

.phead__title{
  font-family:var(--f-display); font-weight:300;
  font-size:clamp(2.6rem,6.4vw,5.2rem); line-height:1.03; letter-spacing:-.018em;
  margin:0 0 1.8rem;
}
.phead__title em{ font-style:italic; color:var(--brass); }
.phead__sub{
  font-size:clamp(1rem,1.5vw,1.16rem); line-height:1.75; color:var(--mute);
  max-width:62ch; margin:0;
}
.phead__jump{ display:flex; flex-wrap:wrap; gap:2.2rem; margin-top:2.8rem; }
.phead__jump a{
  font-size:.74rem; letter-spacing:.18em; text-transform:uppercase; color:var(--bone);
  opacity:.72; padding-bottom:.4rem; border-bottom:1px solid var(--ink-3);
  transition:opacity .35s var(--ease), border-color .35s var(--ease);
}
.phead__jump a:hover{ opacity:1; border-bottom-color:var(--brass); }

/* ---------- section shell ---------------------------------------------- */
/* Arriving from the dropdown puts the section's own top edge at viewport y=0 -- which is
   underneath the fixed bar, so the eyebrow and heading you navigated TO are the two things
   hidden. scroll-margin-top reserves the bar's height plus a breath of air. */
.res,
.phead{ scroll-margin-top:calc(var(--nav-h) + 1.5rem); }
.res{ padding:var(--section) 0; }
.res--alt{ background:var(--ink-2); }
.res__head,
.res__grid,
.res__videos,
.res__slot,
.res__cta,
.webinar{ width:var(--shell); margin-inline:auto; }

.res__head{ max-width:900px; margin-bottom:clamp(3rem,6vh,4.5rem); }
.res__head h2{
  font-family:var(--f-display); font-weight:300;
  font-size:clamp(2rem,4.4vw,3.4rem); line-height:1.08; letter-spacing:-.015em;
  margin:0;
}
.res__note{ font-size:.98rem; line-height:1.75; color:var(--mute); max-width:56ch; margin:1.4rem 0 0; }

/* ---------- article cards ----------------------------------------------- */
/* .card carries a rail-specific flex basis; in a grid track that basis is inert but the
   explicit reset keeps the intent readable to whoever edits this next. */
.res__grid{
  display:grid; grid-template-columns:repeat(3,1fr); gap:clamp(1.2rem,2.2vw,2rem);
}
.res__grid .card{ flex:none; display:flex; flex-direction:column; }
.card__media{ overflow:hidden; aspect-ratio:16/10; background:var(--ink-3); flex:none; }
.card__media img{
  width:100%; height:100%; object-fit:cover;
  filter:saturate(.88) contrast(1.04);
  transition:transform 1.2s var(--slow), filter .6s var(--ease);
}
.card:hover .card__media img{ transform:scale(1.06); filter:saturate(1) contrast(1.04); }
.card__body{ padding:1.7rem; display:flex; flex-direction:column; gap:.75rem; flex:1; }
.card__kicker{
  font-size:.66rem; letter-spacing:.22em; text-transform:uppercase; color:var(--brass);
}
.card__body h3{
  font-family:var(--f-display); font-weight:400;
  font-size:1.22rem; line-height:1.25; margin:0;
}
.card__body p{ font-size:.86rem; line-height:1.65; color:var(--mute); margin:0; }
.card__go{
  margin-top:auto; padding-top:.6rem;
  font-size:.7rem; letter-spacing:.16em; text-transform:uppercase; color:var(--bone);
  opacity:.6; transition:opacity .4s var(--ease), color .4s var(--ease);
}
.card__go::after{ content:" \2192"; }
.card:hover .card__go{ opacity:1; color:var(--brass); }

/* ---------- video grid --------------------------------------------------- */
.res__videos{ display:grid; grid-template-columns:repeat(2,1fr); gap:clamp(1.4rem,2.6vw,2.4rem); }
.film{ margin:0; }
.film figcaption{
  display:flex; flex-direction:column; gap:.3rem; margin-top:1.1rem;
}
.film figcaption strong{ font-size:.95rem; font-weight:500; }
.film figcaption span{ font-size:.74rem; letter-spacing:.14em; text-transform:uppercase; color:var(--mute-d); }

/* ---------- the "your content goes here" slot ---------------------------- */
/* Marked as an invitation, not disguised as a fourth card. A client should never have to
   guess which items on a preview are real. */
.res__slot{
  margin-top:clamp(2rem,4vh,3rem);
  padding:1.5rem 1.7rem;
  border:1px dashed var(--ink-3); border-radius:var(--r);
  background:rgba(181,139,82,.045);
}
.res__slot p{ margin:0; font-size:.85rem; line-height:1.7; color:var(--mute); }
.res__slot strong{ color:var(--bone-2); font-weight:500; }

/* ---------- webinar ------------------------------------------------------ */
/* Layered with positive z-index only. A negative-index child inside a rounded, clipped box
   is the classic way to make a background silently vanish on Safari; there is no reason to
   risk it when three explicit layers say the same thing. */
.webinar{ position:relative; overflow:hidden; border-radius:var(--r); background:var(--ink); }
.webinar__media{ position:absolute; inset:0; z-index:0; }
.webinar__media img{ width:100%; height:100%; object-fit:cover; filter:saturate(.8) contrast(1.06); }
.webinar__scrim{
  position:absolute; inset:0; z-index:1;
  background:linear-gradient(105deg, rgba(11,12,14,.95) 0%, rgba(11,12,14,.86) 46%, rgba(11,12,14,.5) 100%);
}
.webinar__inner{ position:relative; z-index:2; padding:clamp(2.4rem,5vw,4.4rem); max-width:760px; }
.webinar__label{
  font-size:.68rem; letter-spacing:.22em; text-transform:uppercase; color:var(--brass); margin:0 0 1.2rem;
}
.webinar__title{
  font-family:var(--f-display); font-weight:300;
  font-size:clamp(1.7rem,3.6vw,2.7rem); line-height:1.12; margin:0;
}
.webinar__tag{
  font-family:var(--f-display); font-style:italic; color:var(--brass-lt);
  font-size:clamp(1.05rem,1.9vw,1.4rem); margin:.6rem 0 1.5rem;
}
.webinar__body{ font-size:.95rem; line-height:1.8; color:var(--mute); margin:0 0 2rem; max-width:56ch; }
.webinar__meta{
  list-style:none; padding:0; margin:0 0 2.2rem;
  display:flex; flex-wrap:wrap; gap:2.4rem;
  border-top:1px solid var(--ink-3); border-bottom:1px solid var(--ink-3);
  padding-block:1.3rem;
}
.webinar__meta li{ display:flex; flex-direction:column; gap:.35rem; }
.webinar__meta span{ font-size:.64rem; letter-spacing:.2em; text-transform:uppercase; color:var(--mute-d); }
.webinar__meta em{ font-style:normal; font-size:.92rem; color:var(--bone-2); }
.webinar__actions{ display:flex; flex-wrap:wrap; gap:1rem; }
.webinar__fine{ font-size:.74rem; line-height:1.6; color:var(--mute-d); margin:1.6rem 0 0; }

/* ---------- closing band -------------------------------------------------- */
.res--close{ text-align:center; }
.res__cta{ max-width:640px; }
.res__cta h2{
  font-family:var(--f-display); font-weight:300;
  font-size:clamp(1.8rem,3.8vw,2.8rem); line-height:1.12; margin:0 0 1.1rem;
}
.res__cta p{ font-size:.98rem; line-height:1.8; color:var(--mute); margin:0 0 2.2rem; }
.res__cta-actions{ display:flex; flex-wrap:wrap; gap:1rem; justify-content:center; }

@media (max-width:1080px){
  .res__grid{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width:760px){
  .res__grid,
  .res__videos{ grid-template-columns:1fr; }
  .phead__jump{ gap:1.4rem; }
  .webinar__meta{ gap:1.6rem; }
  .webinar__actions .btn{ width:100%; }
  .res__cta-actions .btn{ width:100%; }
}

/* ─────────────────────────────────────────────────────────────────────────────
   Compliance marks, licence line, and the spam trap.

   The three marks are vector, so they stay sharp on a phone — the originals on the
   live site are 31–42px bitmaps and go soft the moment a retina screen doubles them.
   They sit above the small print, quiet and small, which is how the marks are meant
   to be shown: present and legible, not decorative.
   ───────────────────────────────────────────────────────────────────────────── */

.foot__license {
  margin-top: .5rem;
  font-size: .78rem;
  letter-spacing: .02em;
  color: rgba(255, 255, 255, .5);
}

.foot__marks {
  /* Same shell width and centring as the disclaimer and the copyright bar below it,
     otherwise the first mark hangs off the left edge of the page. */
  width: var(--shell);
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: clamp(1.4rem, 3vw, 2.6rem);
  padding-block: 1.9rem;
}

.foot__mark {
  height: 26px;
  width: auto;
  opacity: .62;
  transition: opacity .3s ease;
}

/* The MLS mark is a wide lockup rather than a square, so matching heights would make
   it read twice the size of the other two. Matched on visual weight instead. */
.foot__mark--mls { height: 19px; }

.foot__marks:hover .foot__mark { opacity: .82; }

@media (max-width: 640px) {
  .foot__marks { gap: 1.2rem; justify-content: center; }
  .foot__mark { height: 22px; }
  .foot__mark--mls { height: 16px; }
}

/* Offered to robots, invisible and unreachable for people: off-screen, no tab stop,
   and hidden from assistive technology by the aria-hidden on its wrapper. */
.form__hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}


/* ═══════════════════════════════════════════════════════════════════════════
   HOST-SITE GUARD  (added 2026-08-09)

   Only bites when this stylesheet runs inside WordPress next to a theme. On a
   standalone build every declaration below is a verbatim repeat of the `body`
   rule near the top of this file, so it changes nothing.

   The homepage went live on Astra + Elementor and came back with the headline
   near-black in Cinzel, a dark box behind the "Resources" menu item, and a white
   page ground. The cause is specificity, not load order: our base rules are
   element selectors (`body` = 0,0,1) and Elementor's global kit emits
   `.elementor-kit-7 h1` (0,1,1) while Astra adds `body, h1, h2, ...`. A 0,1,1
   selector wins from anywhere in the cascade, which is why moving our <link>
   later fixed only the line-height.

   DELIBERATELY LIMITED TO <body>. The first draft of this guard also re-asserted
   h1/h2/h3, a, p and button at `body.fre-page button` (0,1,2) -- which beats
   Elementor, but also beats our own `.btn` (0,1,0), so it would have flattened
   every button on the page to fix a problem that had not happened yet. Nothing
   else in this file styles the bare `body` element, so this block can only ever
   collide with the host theme, never with our own components.

   The actual fix is includes/isolate.php, which removes those stylesheets from
   our two pages entirely; this is the floor under it, so a theme update or a new
   plugin can never leave Daniel with a white page and the wrong typeface.
   ═════════════════════════════════════════════════════════════════════════ */
body.fre-page{
  margin:0;
  background:var(--ink);
  color:var(--bone);
  font-family:var(--f-ui);
  font-size:clamp(15px,.55vw + 13px,17px);
  line-height:1.65;
  font-weight:300;
  letter-spacing:.005em;
  overflow-x:hidden;
}
