/* ==========================================================================
   kellyscalone.com — components. Requires tokens.css first.

   COMPLIANCE-DRIVEN DESIGN NOTE (FL Rule 61J2-10.025)
   The rule requires the licensed brokerage name adjacent to every point of
   contact, AND the licensee's personal name to be no larger than the
   brokerage name. So:
     - .lockup__name and .lockup__firm are locked to the SAME font-size via
       one shared custom property. Do not give the name its own size.
     - The oversized hero headline is a VALUE STATEMENT, never her name. That
       keeps the display type dramatic without breaking the rule.
   Changing either of these is a compliance regression, not a style tweak.
   ========================================================================== */

/* Pending-fact marker — deliberately ugly so an unfinished build is obvious. */
.pending {
  background: #FFE8A3; color: #6B4A00; border: 1px dashed #A9761B;
  padding: 0 .35em; font-family: var(--font-body); font-size: .85em;
  font-weight: 600; border-radius: 2px; white-space: nowrap;
}

/* ==========================================================================
   Brand lockup — name + firm at enforced parity
   ========================================================================== */

.lockup { display: flex; flex-direction: column; gap: .3rem; text-decoration: none; }
.lockup { --lockup-size: 1.0625rem; }          /* the single shared size */

.lockup__name,
.lockup__firm {
  font-size: var(--lockup-size);                /* parity — see note above */
  line-height: 1.2;
  font-family: var(--font-body);
  letter-spacing: .06em;
  text-transform: uppercase;
  margin: 0;
}
.lockup__name { font-weight: 700; color: var(--rm-blue); }
.lockup__firm { font-weight: 400; color: var(--muted); letter-spacing: .05em; }
.lockup__rule { width: 2rem; border-top: 1px solid var(--rm-red-ink); margin: .1rem 0; }

.on-dark .lockup__name, .site-header--over .lockup__name { color: var(--white); }
.on-dark .lockup__firm, .site-header--over .lockup__firm { color: rgba(255,255,255,.82); }
.on-dark .lockup__rule, .site-header--over .lockup__rule { border-top-color: var(--rm-red-lift); }

/* ==========================================================================
   Site header (brand pages only — ad landing pages use .lp-bar instead)
   ========================================================================== */

.site-header {
  position: relative; z-index: var(--z-sticky);
  padding-block: var(--s-5);
  border-bottom: 1px solid var(--mist);
  background: var(--paper);
}
/* Transparent variant that sits over a hero image */
.site-header--over {
  background: transparent; border-bottom-color: rgba(255,255,255,.18);
  position: absolute; inset: 0 0 auto 0;
}

.site-header__inner { display: flex; align-items: center; justify-content: space-between; gap: var(--s-6); }

/* The lockup carries two uppercase lines at parity, so it needs room. Cap it
   and let the firm name wrap inside its own block rather than squeezing nav.
   NB: both declarations here are superseded further down the file ("Lockup
   width" / "Header balance at the longer firm name"). Change them THERE. */
.site-header .lockup { flex: 0 1 auto; max-width: 20rem; }

.nav { display: flex; align-items: center; gap: clamp(1rem, 2vw, 1.75rem); }
.nav a {
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; text-decoration: none; color: var(--rm-blue);
  padding: var(--s-2) 0; position: relative;
  white-space: nowrap;   /* two-line nav items read as broken */
}
.site-header--over .nav a { color: rgba(255,255,255,.92); }
.nav a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 0;
  border-bottom: 1px solid var(--rm-red-ink);
  transition: right var(--t-mid) var(--ease);
}
.nav a:hover::after, .nav a[aria-current="page"]::after { right: 0; }
.site-header--over .nav a::after { border-bottom-color: var(--rm-red-lift); }

.nav-toggle { display: none; }

/* Six uppercase nav items plus the two-line compliance lockup run out of
   room well before 860px, so the hamburger takes over at 1024px. */
/* Collapses to the menu button at 1200px. Inherited from the sister site,
   where a seven-item nav beside "RE/MAX Services" pushed
   the document into horizontal overflow between ~1025px and ~1200px -- visible
   only as a scrollWidth larger than the viewport, because body has
   overflow-x:hidden. "RE/MAX Services" is a much shorter firm name, so this
   breakpoint is now conservative rather than load-bearing. It is kept because
   the nav still carries seven items and the headroom costs nothing; if you
   lower it, measure scrollWidth at 1100px before shipping. */
/* Back to 1200px on 2026-08-13 (Bryan-directed), because the IA changed.
   The four town links now sit behind one "Areas" dropdown, which took the nav
   from 902px to roughly 590px against the ~702px the header track allows. It
   had briefly been raised to 1560px, when eight flat items could not fit
   beside the two-line compliance lockup at any laptop width and the Contact
   button painted off the right edge of the viewport at 1440. Grouping was the
   real fix; the raised breakpoint was the holding measure. Do not add more
   top-level items without re-measuring -- the constraint is the ~702px track,
   not the viewport. */
@media (max-width: 1200px) {
  .nav { display: none; }
  .nav.is-open {
    display: flex; flex-direction: column; align-items: flex-start;
    position: absolute; top: 100%; left: 0; right: 0;
    background: var(--paper); border-bottom: 1px solid var(--mist);
    padding: var(--s-5) var(--gutter); gap: var(--s-4);
    box-shadow: var(--shadow-md);
  }
  .nav.is-open a { color: var(--rm-blue); font-size: var(--fs-body); }

  /* Inside the mobile panel the dropdown stops being a dropdown: the towns
     render as a plain indented list under a heading. A nested disclosure here
     would be a second tap to discover inside a menu the visitor already had to
     open, and the panel has the vertical room to just show them. */
  .nav.is-open .nav__group { display: block; width: 100%; }
  .nav.is-open .nav__grouptoggle {
    pointer-events: none; cursor: default;
    color: var(--muted); font-size: var(--fs-micro);
    padding-bottom: var(--s-2);
  }
  .nav.is-open .nav__grouptoggle::after { content: none; }
  .nav.is-open .nav__chev { display: none; }
  .nav.is-open .nav__menu {
    position: static; transform: none; opacity: 1; visibility: visible;
    min-width: 0; padding: 0 0 var(--s-3); margin: 0;
    background: none; border: 0; box-shadow: none;
    gap: var(--s-4);
  }
  .nav.is-open .nav__menu::before { content: none; }
  .nav.is-open .nav__menu a {
    padding: 0 0 0 var(--s-4); font-size: var(--fs-body); letter-spacing: 0;
    border-left: 1px solid var(--mist);
  }
  .nav.is-open .nav__menu a:hover,
  .nav.is-open .nav__menu a:focus-visible { background: none; color: var(--rm-red-ink); }
  .nav-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; background: none; border: 1px solid currentColor;
    border-radius: var(--r-sm); cursor: pointer; color: var(--rm-blue);
  }
  .site-header--over .nav-toggle { color: var(--white); }
}

/* ==========================================================================
   Hero — full-bleed photo, layered overlay, ASYMMETRIC text (not centered)
   ========================================================================== */

.hero { position: relative; isolation: isolate; background: var(--rm-blue-deep); }
.hero__media { position: absolute; inset: 0; z-index: -2; overflow: hidden; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }

/* Two-layer overlay: a directional gradient for text legibility plus a warm
   tint so the photo sits in the palette instead of fighting it. */
.hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(100deg, rgba(0,36,107,.90) 0%, rgba(0,36,107,.72) 38%,
                    rgba(0,36,107,.30) 68%, rgba(0,36,107,.12) 100%),
    linear-gradient(to top, rgba(0,36,107,.55) 0%, rgba(0,36,107,0) 45%);
}

.hero__inner {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  align-items: end; gap: var(--s-8);
  padding-block: clamp(8rem, 20vh, 13rem) clamp(6rem, 13vh, 9.5rem);
  min-height: min(88vh, 900px);
}
@media (max-width: 900px) {
  .hero__inner { grid-template-columns: 1fr; align-items: start; gap: var(--s-6);
                 padding-block: clamp(7rem, 18vh, 10rem) var(--s-8);
                 min-height: auto; }
}

.hero__title {
  font-size: var(--fs-hero); color: var(--white);
  line-height: var(--lh-display); letter-spacing: var(--ls-display);
  margin: 0 0 var(--s-5); max-width: 22ch;
}
.hero__title em {
  font-style: italic; color: var(--rm-red-lift);   /* 8.07:1 on navy-deep */
}
.hero__lead {
  color: rgba(255,255,255,.90); font-size: var(--fs-lead);
  max-width: 46ch; margin: 0 0 var(--s-6);
}
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--s-5); align-items: center; }

/* Secondary hero action is a quiet text link, not a second button. Two equal
   buttons split attention (conversion research: ONE explicit CTA per view) and
   at 1440px they overflowed the 7fr column and wrapped under the primary. */
.hero__alt {
  display: inline-flex; align-items: center; gap: .5rem;
  min-height: 44px; font-size: var(--fs-small); font-weight: 600;
  letter-spacing: .02em; color: var(--white); text-decoration: none;
  border-bottom: 1px solid rgba(201,165,95,.6); padding-bottom: 2px;
  transition: color var(--t-mid) var(--ease), border-color var(--t-mid) var(--ease);
}
.hero__alt:hover { color: var(--rm-red-lift); border-bottom-color: var(--rm-red-lift); }
.hero__alt svg { transition: transform var(--t-mid) var(--ease); }
.hero__alt:hover svg { transform: translateX(3px); }

/* Small stat/credential strip in the hero's right column. Only renders facts
   that exist — never a fabricated number. */
.hero__aside {
  border-left: 1px solid rgba(201,165,95,.45);
  padding-left: var(--s-5);
}
.hero__aside dl { margin: 0; display: grid; gap: var(--s-5); }
.hero__aside dt {
  font-size: var(--fs-micro); letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase; color: var(--rm-red-lift); font-weight: 600;
  margin-bottom: .2rem;
}
.hero__aside dd {
  margin: 0; color: var(--white); font-family: var(--font-display);
  font-size: 1.35rem; line-height: 1.25;
}
@media (max-width: 900px) {
  .hero__aside { border-left: 0; border-top: 1px solid rgba(201,165,95,.45);
                 padding-left: 0; padding-top: var(--s-5); }
  .hero__aside dl { grid-template-columns: 1fr 1fr; gap: var(--s-4) var(--s-5); }
}

/* ==========================================================================
   Overlapping panel — depth via layered surfaces (required quality #3)
   ========================================================================== */

.overlap {
  position: relative; z-index: var(--z-raised);
  margin-top: clamp(-4rem, -5vw, -2.5rem);
  background: var(--paper); box-shadow: var(--shadow-lg);
  padding: clamp(2rem, 5vw, 3.5rem);
  max-width: 62rem;
}
@media (max-width: 700px) { .overlap { margin-top: -2rem; padding: var(--s-6) var(--s-5); } }

/* ==========================================================================
   Editorial / bento composition — deliberately NOT a uniform card grid
   ========================================================================== */

/* Four towns, so four cards. Above 1200px they hold one row -- "the markets"
   is meant to be scanned in a single sweep. Between 900 and 1200 that would
   put each card near 280px, so it folds to a 2x2 instead. Below 900 the snap
   rail further down takes over.

   The grid-break is now a translateY stagger only. It used to also give the
   middle card a taller 4/4.6 aspect-ratio, which worked with three cards in
   one row; with four cards wrapping to two rows, a taller card sets its whole
   grid row's height and the shorter card beside it ends up with dead space
   under an absolutely-positioned .market__body. transform is visual-only and
   never affects row height, so the stagger survives the rewrap intact. */
.markets { display: grid; gap: var(--s-5); grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1200px) { .markets { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 900px)  { .markets { grid-template-columns: 1fr; } }

/* SINGLE-CELL GRID STACK, not position:absolute.
   The card previously laid the body out with `position: absolute; inset: auto
   0 0 0` over a 4:3 media box, so the card's height came from the IMAGE alone.
   Any card whose text needed a second line grew upward, past the top of an
   overflow:hidden box, and silently clipped its own eyebrow. Measured before
   this change: 1 of 4 cards clipped on the homepage ("Palm Beach Gardens") and
   8 of 8 on /buying/ and /selling/ ("Buying in ...", "Selling in ...").

   Stacking all three children in one grid cell makes the row height
   max(aspect-ratio spacer, body content), so the card grows to fit its text
   and the image stretches with it. Nothing can clip. This also means a longer
   town name or a reworded cue is safe without re-measuring. */
.market { position: relative; text-decoration: none; overflow: hidden;
          background: var(--rm-blue);
          display: grid; grid-template-columns: 1fr; grid-template-rows: auto; }
/* Establishes the 4:3 MINIMUM height. A zero-width padding-top box is the only
   way to express "at least this aspect ratio" that also participates in grid
   row sizing. */
.market::before { content: ""; grid-area: 1 / 1; padding-top: 75%; }
.markets .market:nth-child(even) { transform: translateY(var(--s-6)); }
@media (max-width: 900px) { .markets .market:nth-child(even) { transform: none; } }

/* Inside the Gates listing. Borrows the market card, but NOT its four-column track:
   the town grid is fixed at four because there are four towns, whereas the post
   count changes every time something is published. auto-fit means three posts
   fill the row instead of leaving a dead fourth column, and a fourth post does
   not require anyone to remember to edit this file. */
.notes { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }
@media (max-width: 1200px) { .notes { grid-template-columns: repeat(2, 1fr); } }

/* No aspect-ratio here any more -- .market::before carries it. As a grid item
   with auto height this stretches to the full row, so it fills the card even
   when the body has made the card taller than 4:3. */
.market__media { grid-area: 1 / 1; overflow: hidden; }

.market__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform var(--t-slow) var(--ease-out), filter var(--t-slow) var(--ease-out);
  filter: saturate(.94);
}
/* Zoom the IMAGE inside a fixed frame — no layout shift on hover. */
.market:hover .market__media img { transform: scale(1.05); filter: saturate(1.04); }

.market__body {
  grid-area: 1 / 1; align-self: end; position: relative;
  padding: var(--s-8) var(--s-5) var(--s-5);
  /* Strengthened: the offset middle card puts its eyebrow over bright water,
     where the previous ramp left the accent label under 4.5:1. */
  background: linear-gradient(to top, rgba(0,36,107,.96) 0%, rgba(0,36,107,.88) 42%,
                              rgba(0,36,107,.55) 75%, rgba(0,36,107,0) 100%);
}
.market__name {
  font-family: var(--font-display); font-weight: 700; color: var(--white);
  margin: 0 0 .25rem; line-height: 1.15;
  /* Fluid, and capped BELOW the old flat 1.6rem. .market__body is
     bottom-anchored inside an overflow:hidden card, so a name that wraps to a
     second line pushes the body's top edge past the card and the meta eyebrow
     above it gets clipped away. That is exactly what "Palm Beach Gardens" --
     the longest town name on this site -- did at the four-column width.
     Sized so that name fits on ONE line in a 4-col track at 1440.
     If a longer town is ever added, re-measure rather than assuming. */
  font-size: clamp(1.3rem, 1.05vw + .82rem, 1.5rem);
}
.market__meta {
  font-size: var(--fs-micro); letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase; color: var(--rm-red-lift); font-weight: 600;
}
.market__cue {
  display: inline-flex; align-items: center; gap: .5rem; margin-top: var(--s-3);
  font-size: var(--fs-small); font-weight: 600; color: var(--white);
}
.market__cue svg { transition: transform var(--t-mid) var(--ease); }
.market:hover .market__cue svg { transform: translateX(4px); }

/* ==========================================================================
   Editorial split — asymmetric two-column with generous negative space
   ========================================================================== */

.split { display: grid; grid-template-columns: minmax(0,5fr) minmax(0,6fr); gap: clamp(2rem,6vw,5rem); align-items: center; }
.split--reverse > :first-child { order: 2; }
/* Copy-first variant (wider text column, narrower media). Must stay ABOVE the
   max-width:900px block: it has the same specificity as `.split`, so only
   source order lets the mobile single-column collapse override it. This exists
   because an inline style attribute was previously used for the same effect on
   /buying/ — inline styles outrank the media query entirely, which pinned that
   section to two columns on phones and tablets. Never re-inline this. */
.split--wide-first { grid-template-columns: minmax(0,6fr) minmax(0,5fr); }
@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; gap: var(--s-6); }
  .split--reverse > :first-child { order: 0; }
}
.split__media { position: relative; }
.split__media img { width: 100%; box-shadow: var(--shadow-lg); }
/* Offset accent frame behind the image — depth without a drop-shadow cliche. */
.split__media::before {
  content: ""; position: absolute; inset: auto auto -14px -14px;
  width: 62%; height: 62%; border-left: 2px solid var(--rm-red-ink);
  border-bottom: 2px solid var(--rm-red-ink); z-index: -1;
}

/* Pull quote / statement block */
.statement {
  font-family: var(--font-display); font-size: var(--fs-h2);
  line-height: 1.22; letter-spacing: var(--ls-display);
  max-width: 34ch; margin: 0;
}
.section--dark .statement, .section--ink .statement { color: var(--white); }

/* Numbered process list — editorial, not a card grid */
.steps { list-style: none; margin: 0; padding: 0; counter-reset: step; display: grid; gap: var(--s-6); }
.steps li { counter-increment: step; display: grid; grid-template-columns: 3.25rem 1fr; gap: var(--s-4); }
.steps li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-display); font-size: 1.5rem; color: var(--rm-red-ink);
  line-height: 1; padding-top: .15rem;
}
.section--dark .steps li::before, .section--ink .steps li::before { color: var(--rm-red-lift); }
.steps h3 { font-family: var(--font-body); font-size: 1.0625rem; font-weight: 600; margin: 0 0 .3rem; }
.section--dark .steps h3 { color: var(--white); }
.steps p { margin: 0; font-size: var(--fs-small); color: var(--muted); max-width: 44ch; }
.section--dark .steps p, .section--ink .steps p { color: rgba(227,231,237,.86); }

/* ==========================================================================
   Landing-page chrome — NO nav, single exit. Conversion research: remove
   every competing link from an ad destination.
   ========================================================================== */

.lp-bar {
  background: var(--rm-blue-ink); color: var(--white);
  padding-block: var(--s-4); position: relative; z-index: var(--z-sticky);
}
.lp-bar__inner { display: flex; align-items: center; justify-content: space-between; gap: var(--s-5); flex-wrap: wrap; }
.lp-bar .lockup__name { color: var(--white); }
.lp-bar .lockup__firm { color: rgba(255,255,255,.82); }
.lp-bar .lockup__rule { border-top-color: var(--rm-red-lift); }
.lp-bar__contact {
  display: flex; align-items: center; gap: var(--s-5); flex-wrap: wrap;
  font-size: var(--fs-small);
}
/* These two ARE the conversion on mobile (click-to-call / click-to-text), so
   they get full 44px targets rather than inline-link treatment. Measured at
   38px and 24px before this rule. */
.lp-bar__contact a {
  color: var(--white); font-weight: 600; text-decoration: none;
  display: inline-flex; align-items: center;
  min-height: 44px; padding-inline: var(--s-2);
}
.lp-bar__contact a:hover { color: var(--rm-red-lift); }

/* ==========================================================================
   Multi-step form — research: +40-60% completion vs a single long form
   ========================================================================== */

.leadform {
  background: var(--white); box-shadow: var(--shadow-lg);
  padding: clamp(1.5rem, 4vw, 2.5rem);
  border-top: 3px solid var(--rm-red-ink);
}
.leadform__head { margin-bottom: var(--s-5); }
.leadform__title { font-size: 1.5rem; margin: 0 0 var(--s-2); }
.leadform__sub { font-size: var(--fs-small); color: var(--muted); margin: 0; }

/* Progress — reserved height so advancing a step never shifts layout */
.progress { display: flex; align-items: center; gap: var(--s-2); margin-bottom: var(--s-5); }
.progress__seg { flex: 1; height: 3px; background: var(--mist); position: relative; overflow: hidden; }
.progress__seg::after {
  content: ""; position: absolute; inset: 0; background: var(--rm-red-ink);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--t-mid) var(--ease);
}
.progress__seg.is-done::after, .progress__seg.is-current::after { transform: scaleX(1); }
.progress__label {
  font-size: var(--fs-micro); letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); font-weight: 600; white-space: nowrap;
}

.step__h {
  font-family: var(--font-body); font-size: 1.0625rem; font-weight: 600;
  color: var(--rm-blue); margin: 0 0 var(--s-4); letter-spacing: .01em;
}
.step__h:focus { outline: none; }   /* focused programmatically on step change */

.step { display: none; }
.js-stepped .step { display: none; }
.step.is-active { display: block; animation: stepIn var(--t-mid) var(--ease-out); }
@keyframes stepIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .step.is-active { animation: none; } }

.step__actions { display: flex; gap: var(--s-3); align-items: center; margin-top: var(--s-5); }
.btn-back {
  background: none; border: 0; cursor: pointer; color: var(--muted);
  font-family: var(--font-body); font-size: var(--fs-small); font-weight: 600;
  padding: var(--s-3) var(--s-2); min-height: 44px;
}
.btn-back:hover { color: var(--rm-blue); }

/* Choice chips — larger tap targets than a select, and faster to answer */
.chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.chips input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.chips label {
  display: inline-flex; align-items: center; min-height: 46px;
  padding: var(--s-2) var(--s-5); margin: 0; cursor: pointer;
  border: 1px solid #B9B2A4; border-radius: var(--r-pill);
  font-size: var(--fs-small); font-weight: 500; color: var(--rm-blue);
  background: var(--white);
  transition: background-color var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.chips label:hover { border-color: var(--rm-red-ink); }
.chips input:checked + label { background: var(--rm-blue-ink); border-color: var(--rm-blue-ink); color: var(--white); }
.chips input:focus-visible + label { outline: 2px solid var(--rm-red-ink); outline-offset: 3px; }

.trust-line {
  display: flex; align-items: flex-start; gap: var(--s-2);
  font-size: var(--fs-micro); color: var(--muted); margin-top: var(--s-4);
}
.trust-line svg { flex: 0 0 auto; margin-top: .15em; color: var(--rm-red-ink); }

/* Benefit bullets beside the form */
.benefits { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-4); }
.benefits li { display: grid; grid-template-columns: 1.5rem 1fr; gap: var(--s-3); align-items: start; }
.benefits svg { color: var(--rm-red-lift); margin-top: .2em; }
.section--dark .benefits li, .hero .benefits li { color: rgba(255,255,255,.92); }
.benefits strong { display: block; font-weight: 600; margin-bottom: .15rem; }

/* LP hero variant: copy left, form right */
.lp-hero__inner {
  display: grid; grid-template-columns: minmax(0,6fr) minmax(0,5fr);
  gap: clamp(2rem, 5vw, 4.5rem); align-items: center;
  padding-block: clamp(3.5rem, 9vh, 6rem);
}
@media (max-width: 960px) { .lp-hero__inner { grid-template-columns: 1fr; } }

/* ==========================================================================
   FAQ — native details/summary, keyboard-accessible for free
   ========================================================================== */

.faq { border-top: 1px solid var(--mist); }
.faq details { border-bottom: 1px solid var(--mist); }
.faq summary {
  cursor: pointer; list-style: none; padding: var(--s-5) var(--s-6) var(--s-5) 0;
  font-family: var(--font-body); font-weight: 600; font-size: 1.0625rem;
  color: var(--rm-blue); position: relative; min-height: 44px;
  display: flex; align-items: center;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: .35rem; top: 50%;
  width: 10px; height: 10px; margin-top: -6px;
  border-right: 1.5px solid var(--rm-red-ink); border-bottom: 1.5px solid var(--rm-red-ink);
  transform: rotate(45deg); transition: transform var(--t-mid) var(--ease);
}
.faq details[open] summary::after { transform: rotate(225deg); margin-top: -2px; }
.faq summary:hover { color: var(--rm-red-ink); }
.faq__body { padding: 0 var(--s-6) var(--s-5) 0; }
.faq__body p { font-size: var(--fs-body); color: var(--muted); margin: 0 0 var(--s-3); }
.faq__body p:last-child { margin-bottom: 0; }

/* ==========================================================================
   Compliance footer — brokerage name ADJACENT to every contact point
   ========================================================================== */

.site-footer { background: var(--rm-blue-ink); color: rgba(227,231,237,.84); padding-block: var(--s-8) var(--s-6); }
.site-footer a { color: var(--white); }
.site-footer a:hover { color: var(--rm-red-lift); }

.footer__grid {
  display: grid; grid-template-columns: minmax(0,4fr) minmax(0,3fr) minmax(0,4fr);
  gap: var(--s-7); padding-bottom: var(--s-7);
  border-bottom: 1px solid rgba(255,255,255,.14);
}
@media (max-width: 860px) { .footer__grid { grid-template-columns: 1fr; gap: var(--s-6); } }

.footer__h {
  font-family: var(--font-body); font-size: var(--fs-micro); font-weight: 700;
  letter-spacing: var(--ls-eyebrow); text-transform: uppercase;
  color: var(--rm-red-lift); margin: 0 0 var(--s-4);
}
.footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-3); }
.footer__list a { font-size: var(--fs-small); text-decoration: none; }
.footer__list a:hover { text-decoration: underline; }

/* The contact block. The brokerage name sits immediately above the contact
   details — this adjacency is the FL 61J2-10.025 requirement. */
.nap { font-size: var(--fs-small); line-height: 1.7; }
.nap__firm { color: var(--white); font-weight: 700; margin: 0 0 .2rem; }
.nap__agent { color: rgba(227,231,237,.84); margin: 0 0 var(--s-3); }
.nap a { text-decoration: none; font-weight: 600; }

.legal { padding-top: var(--s-6); display: grid; gap: var(--s-4); }
.legal p { font-size: var(--fs-micro); line-height: 1.65; margin: 0; max-width: 88ch;
           color: rgba(227,231,237,.78); }   /* verified >=4.5:1 on --rm-blue-ink */
.legal__badges { display: flex; align-items: center; gap: var(--s-5); flex-wrap: wrap; }
.legal__badge {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: rgba(227,231,237,.9);
}
.legal__badge svg { flex: 0 0 auto; }

/* ==========================================================================
   Thank-you page — speed-to-lead surface. Lead delivery is email-only, so
   this page carries the "reach her right now" job.
   ========================================================================== */

.ty { text-align: center; max-width: 44rem; margin-inline: auto; }
.ty__mark {
  width: 62px; height: 62px; margin: 0 auto var(--s-5);
  display: grid; place-items: center; border-radius: 50%;
  background: var(--rm-red-ink); color: var(--white);
}
.ty__next {
  text-align: left; background: var(--white); box-shadow: var(--shadow-md);
  padding: clamp(1.5rem,4vw,2.25rem); margin-top: var(--s-7);
  border-left: 3px solid var(--rm-red-ink);
}
.ty__actions { display: flex; flex-wrap: wrap; gap: var(--s-4); justify-content: center; margin-top: var(--s-6); }

/* ==========================================================================
   Misc
   ========================================================================== */

.prose { max-width: var(--maxw-text); }
.prose h2 { margin-top: var(--s-8); }
.prose h3 { margin-top: var(--s-6); }
.prose ul, .prose ol { padding-left: 1.15rem; }
.prose li { margin-bottom: var(--s-2); max-width: var(--measure); }

/* Answer block — the <=50-word passage that AI search extracts */
.answer {
  font-size: var(--fs-lead); line-height: 1.5; color: var(--rm-blue-ink);
  border-left: 2px solid var(--rm-red-ink); padding-left: var(--s-5);
  margin: 0 0 var(--s-6); max-width: 52ch;
}

.source-note { font-size: var(--fs-micro); color: var(--muted); font-style: italic; }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-6); }
@media (max-width: 760px) { .grid-2 { grid-template-columns: 1fr; } }

/* ==========================================================================
   Area page components
   ========================================================================== */

/* Neighbourhood list — editorial columns with hairline separators rather than
   a uniform card grid (which the banned-patterns rule rules out). */
.hoods {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 0 clamp(2rem, 5vw, 4rem); margin-top: var(--s-7);
}
@media (max-width: 780px) { .hoods { grid-template-columns: 1fr; } }

.hood { padding: var(--s-6) 0; border-top: 1px solid var(--mist); }
.hood h3 {
  font-family: var(--font-display); font-size: 1.3rem; color: var(--rm-blue);
  margin: 0 0 var(--s-3);
}
.hood p { margin: 0; font-size: var(--fs-small); color: var(--muted); max-width: 42ch; }

/* Checklist — accent ticks, used for the price-driver list on dark */
.checklist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-4); }
.checklist li {
  position: relative; padding-left: 2rem; font-size: var(--fs-body);
  color: rgba(227,231,237,.92); max-width: 46ch;
}
.checklist li::before {
  content: ""; position: absolute; left: 0; top: .48em;
  width: 11px; height: 6px;
  border-left: 1.8px solid var(--rm-red-lift);
  border-bottom: 1.8px solid var(--rm-red-lift);
  transform: rotate(-45deg);
}
.section--mist .checklist li, .section:not(.section--dark):not(.section--ink) .checklist li {
  color: var(--rm-blue-ink);
}
.section:not(.section--dark):not(.section--ink) .checklist li::before {
  border-left-color: var(--rm-red-ink); border-bottom-color: var(--rm-red-ink);
}

/* Market stats — renders em-dashes honestly when no sourced data exists */
.stats {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: var(--s-5); margin: var(--s-6) 0 var(--s-5);
  border-top: 1px solid var(--mist); padding-top: var(--s-6);
}
@media (max-width: 780px) { .stats { grid-template-columns: repeat(2, 1fr); } }

.stat dt {
  font-size: var(--fs-micro); letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); font-weight: 600; margin-bottom: var(--s-2);
}
.stat dd {
  margin: 0; font-family: var(--font-display); font-size: 2rem;
  color: var(--rm-blue); line-height: 1;
}

/* An odd final neighbourhood spans both columns rather than sitting orphaned
   beside an empty cell (Palm Beach Gardens has three). Reads as intentional
   editorial emphasis instead of a layout gap. */
.hood:last-child:nth-child(odd) { grid-column: 1 / -1; }
.hood:last-child:nth-child(odd) p { max-width: 62ch; }

/* ==========================================================================
   PREMIUM LAYER — added 2026-07-30
   Motion, depth and conversion furniture layered ON TOP of the base system.
   Nothing here redefines a base component; it only adds new classes and
   scoped enhancements, so the contrast and name-parity guarantees in
   tokens.css / the compliance lockup are untouched.

   Every animated property is transform/opacity only (compositor-friendly),
   and every block is disabled under prefers-reduced-motion at the end.
   ========================================================================== */

/* ---- Nav: the Areas dropdown -------------------------------------------
   Opening is CSS-first (:hover and :focus-within), so the menu is reachable
   with JS disabled and by keyboard Tab alone. site.js layers click-toggle and
   Escape on top by setting [data-open], which this file also honours.
   visibility+opacity rather than display:none, because display cannot be
   transitioned and, more importantly, :focus-within never fires on a subtree
   that is display:none -- the keyboard path would silently not work. */
.nav__group { position: relative; display: flex; align-items: center; }

.nav__grouptoggle {
  display: inline-flex; align-items: center; gap: .4rem;
  font: inherit; font-size: var(--fs-micro); font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  background: none; border: 0; padding: var(--s-2) 0; margin: 0;
  color: var(--rm-blue); cursor: pointer; white-space: nowrap;
  position: relative;
}
.site-header--over .nav__grouptoggle { color: rgba(255,255,255,.92); }

/* Same underline sweep the sibling links use, so the control reads as nav. */
.nav__grouptoggle::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 0;
  border-bottom: 1px solid var(--rm-red-ink);
  transition: right var(--t-mid) var(--ease);
}
.nav__group:hover .nav__grouptoggle::after,
.nav__group:focus-within .nav__grouptoggle::after,
.nav__grouptoggle[aria-current="page"]::after { right: 0; }
.site-header--over .nav__grouptoggle::after { border-bottom-color: var(--rm-red-lift); }

.nav__chev { transition: transform var(--t-mid) var(--ease); flex: 0 0 auto; }
.nav__group:hover .nav__chev,
.nav__group:focus-within .nav__chev,
.nav__group[data-open] .nav__chev { transform: rotate(180deg); }

/* NO-JS BASE: the towns stay inline, exactly as they were before the grouping.
   A closed panel is only safe to render where something can reopen it, and the
   header's menu button already requires JS, so this keeps the four links
   reachable in the one case where neither control works. */
.nav__menu { display: flex; align-items: center; gap: clamp(.7rem, 1.35vw, 1.2rem); }
.nav__group:not([data-nav-dropdown]) .nav__chev,
html:not(.has-js) .nav__chev { display: none; }
html:not(.has-js) .nav__grouptoggle { display: none; }

/* JS PRESENT: real disclosure. */
.has-js .nav__menu {
  position: absolute; top: calc(100% + var(--s-3)); left: 50%;
  transform: translate(-50%, -.35rem);
  flex-direction: column; gap: 0;
  min-width: 13rem; padding: var(--s-3) 0;
  background: var(--paper);
  border: 1px solid var(--mist);
  box-shadow: var(--shadow-md);
  opacity: 0; visibility: hidden;
  transition: opacity var(--t-mid) var(--ease),
              transform var(--t-mid) var(--ease),
              visibility var(--t-mid) var(--ease);
  z-index: 60;
}
/* A hit-bridge across the gap, so the pointer does not fall through the
   whitespace between the control and the menu and close it mid-travel. */
.nav__menu::before {
  content: ""; position: absolute; left: 0; right: 0;
  top: calc(var(--s-3) * -1); height: var(--s-3);
}
.has-js .nav__group:hover .nav__menu,
.has-js .nav__group:focus-within .nav__menu,
.has-js .nav__group[data-open] .nav__menu {
  opacity: 1; visibility: visible; transform: translate(-50%, 0);
}

/* Escape must win even though the pointer is still parked on the control and
   the button still holds focus -- both of which the two rules above would
   otherwise keep open. site.js sets data-escaped and clears it on mouseleave
   or the next deliberate open, so hovering away and back behaves normally.
   Higher specificity than the open rules, so no !important is needed. */
.has-js .nav__group[data-escaped]:hover .nav__menu,
.has-js .nav__group[data-escaped]:focus-within .nav__menu {
  opacity: 0; visibility: hidden; transform: translate(-50%, -.35rem);
}

.nav__menu a {
  display: block; padding: .55rem var(--s-5);
  color: var(--rm-blue); font-size: var(--fs-micro); letter-spacing: .06em;
  white-space: nowrap;
  transition: background-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
/* The sweep underline is wrong inside a panel — it would animate across a
   full-width row. A ground tint is the panel-appropriate hover. */
.nav__menu a::after { content: none; }
.nav__menu a:hover,
.nav__menu a:focus-visible { background: var(--mist); }
.nav__menu a[aria-current="page"] { color: var(--rm-red-ink); font-weight: 600; }
/* The panel is always light, even under .site-header--over, so its links must
   NOT inherit the white on-dark colour from the header rule. */
.site-header--over .nav__menu a { color: var(--rm-blue); }
.site-header--over .nav__menu a[aria-current="page"] { color: var(--rm-red-ink); }

@media (prefers-reduced-motion: reduce) {
  .nav__menu { transition: none; }
  .nav__chev { transition: none; }
}

/* ---- Nav: buyer + seller intent read as actions, not more links --------- */
.nav__sep {
  width: 1px; height: 1.15rem; background: var(--mist); opacity: .55;
  flex: 0 0 auto;
}
.site-header--over .nav__sep { background: rgba(255,255,255,.34); opacity: 1; }

.nav a.nav__intent { font-weight: 600; }
.nav a.nav__cta {
  font-weight: 600;
  border: 1px solid var(--rm-blue);
  padding: .5rem 1rem;
  border-radius: var(--r-sm);
  transition: background-color var(--t-mid) var(--ease),
              color var(--t-mid) var(--ease),
              border-color var(--t-mid) var(--ease);
}
.nav a.nav__cta::after { content: none; }   /* no underline sweep on a button */
.nav a.nav__cta:hover { background: var(--rm-blue); color: var(--white); }
.site-header--over .nav a.nav__cta { border-color: rgba(255,255,255,.6); }
.site-header--over .nav a.nav__cta:hover {
  background: var(--white); color: var(--rm-blue-ink); border-color: var(--white);
}

/* ---- Reading progress — a hairline of RE/MAX red, not a loading bar ---------- */
.scroll-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px;
  z-index: var(--z-modal); pointer-events: none;
  background: linear-gradient(90deg, var(--rm-red-ink), var(--rm-red-lift));
  transform: scaleX(0); transform-origin: 0 50%;
  will-change: transform;
}

/* ---- Sticky quick-action bar -------------------------------------------
   Appears only after the hero has left the viewport. It does NOT replace the
   primary nav (which stays in markup); it is a complementary shortcut to the
   two intent paths and the phone, which is where conversion actually happens
   once someone has read far enough to care. */
.quickbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: var(--z-sticky);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-5);
  padding: .7rem var(--gutter);
  background: rgba(247,248,250,.86);
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  backdrop-filter: saturate(1.6) blur(14px);
  border-bottom: 1px solid var(--mist);
  box-shadow: 0 1px 0 rgba(11,27,51,.03), 0 10px 30px rgba(11,27,51,.07);
  transform: translateY(-101%);
  transition: transform var(--t-mid) var(--ease-out);
}
.quickbar.is-in { transform: translateY(0); }
.quickbar__name {
  font-family: var(--font-display); font-size: 1.0625rem; color: var(--rm-blue);
  letter-spacing: -.01em; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis;
}
.quickbar__actions { display: flex; align-items: center; gap: var(--s-4); flex: 0 0 auto; }
.quickbar__actions a {
  font-size: var(--fs-small); font-weight: 600; text-decoration: none;
  color: var(--rm-blue); white-space: nowrap;
}
.quickbar__actions a:hover { color: var(--rm-red-ink); }
.quickbar__call {
  display: inline-flex; align-items: center; gap: .45rem;
  background: var(--rm-blue-ink); color: var(--white) !important;
  padding: .6rem 1.05rem; border-radius: var(--r-sm);
  transition: background-color var(--t-mid) var(--ease);
}
.quickbar__call:hover { background: var(--rm-red-ink); color: var(--white) !important; }
@media (max-width: 720px) { .quickbar { display: none; } }

/* ---- Hero: slow drift + staggered entrance ------------------------------
   A 28s scale from 1 to 1.06. Slow enough to read as a photograph breathing
   rather than an animation, which is the difference between expensive and
   gimmicky. GPU-composited, so it costs nothing on scroll. */
.hero--page .hero__media img { transform-origin: 52% 48%; }
.hero__media--kenburns img { animation: kenburns 28s var(--ease) forwards; }
@keyframes kenburns { from { transform: scale(1); } to { transform: scale(1.06); } }

.stagger > * { opacity: 0; transform: translateY(14px); animation: riseIn .78s var(--ease-out) forwards; }
.stagger > *:nth-child(1) { animation-delay: .06s; }
.stagger > *:nth-child(2) { animation-delay: .16s; }
.stagger > *:nth-child(3) { animation-delay: .26s; }
.stagger > *:nth-child(4) { animation-delay: .36s; }
.stagger > *:nth-child(5) { animation-delay: .46s; }
.stagger > *:nth-child(6) { animation-delay: .56s; }
@keyframes riseIn { to { opacity: 1; transform: none; } }

/* Staggered list items reveal after their container enters the viewport. */
.reveal.is-in .stagger > *,
.stagger.is-in > * { animation-play-state: running; }

/* ---- Image mask wipe — reveals the photo, not just fades it ------------- */
.reveal--mask { overflow: hidden; }
.reveal--mask img {
  clip-path: inset(0 0 100% 0);
  transform: scale(1.04);
  transition: clip-path 1s var(--ease-out), transform 1.4s var(--ease-out);
}
.reveal--mask.is-in img { clip-path: inset(0 0 0 0); transform: scale(1); }

/* ---- Trust strip — the four things a luxury lead checks before calling -- */
.trustbar {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: var(--s-5);
  margin-top: calc(var(--s-8) * -1);
  position: relative; z-index: var(--z-raised);
  background: var(--white);
  border: 1px solid var(--mist);
  border-top: 3px solid var(--rm-red-ink);
  padding: var(--s-6) var(--s-7);
  box-shadow: var(--shadow-lg);
}
.trustbar__item { display: grid; gap: .3rem; align-content: start; }
.trustbar__k {
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase; color: var(--rm-red-ink);
}
.trustbar__v { font-size: var(--fs-small); color: var(--rm-blue); font-weight: 500; line-height: 1.45; }
.trustbar__v a { color: var(--rm-blue); font-weight: 600; text-decoration: none; }
.trustbar__v a:hover { color: var(--rm-red-ink); }
@media (max-width: 900px) {
  .trustbar { grid-template-columns: repeat(2, 1fr); padding: var(--s-5); margin-top: var(--s-6); }
}
@media (max-width: 520px) { .trustbar { grid-template-columns: 1fr; } }

/* ---- Closing CTA block -------------------------------------------------- */
.closer {
  max-width: 46rem; border-left: 3px solid var(--rm-red-ink);
  padding-left: clamp(1.25rem, 4vw, 3rem);
}

/* ---- Primary CTA: light sweep on hover ------------------------------------
   A single pass of light across the button. Uses a pseudo-element transform,
   so the button itself never moves and no layout shifts. */
.btn--primary { position: relative; overflow: hidden; isolation: isolate; }
.btn--primary::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(105deg, transparent 35%, rgba(255,255,255,.28) 50%, transparent 65%);
  transform: translateX(-120%);
  transition: transform var(--t-slow) var(--ease-out);
}
.btn--primary:hover::after, .btn--primary:focus-visible::after { transform: translateX(120%); }

/* ---- Sticky mobile action bar ------------------------------------------
   Call and text ARE the conversion on a phone. 52px targets, well above the
   44px minimum. Hidden when a form field has focus so it cannot cover the
   input being typed into (added via .is-hidden by site.js). */
.mobile-cta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sticky);
  display: none; gap: 1px;
  background: var(--mist);
  padding-bottom: env(safe-area-inset-bottom, 0);
  box-shadow: 0 -6px 24px rgba(11,27,51,.16);
  transition: transform var(--t-mid) var(--ease);
}
.mobile-cta.is-hidden { transform: translateY(110%); }
.mobile-cta__btn {
  flex: 1; min-height: 56px;
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: var(--font-body); font-size: var(--fs-body); font-weight: 600;
  text-decoration: none; letter-spacing: .01em;
}
.mobile-cta__btn--call { background: var(--rm-blue-ink); color: var(--white); flex: 1.6; }
.mobile-cta__btn--text { background: var(--rm-red-ink); color: var(--white); }
.mobile-cta__btn:hover, .mobile-cta__btn:focus-visible { color: var(--white); }
@media (max-width: 767px) {
  .mobile-cta { display: flex; }
  /* Keep the last section clear of the fixed bar. */
  .site-footer { padding-bottom: calc(56px + var(--s-6)); }
}

/* ---- Paper grain — atmosphere, at 3% opacity ---------------------------
   Fixed, non-interactive, and behind everything. This is what stops large
   flat bone-coloured areas reading as "default background". */
/* The grain sits ON TOP of the page at 2.8% and is click-through, so nothing
   else has to be repositioned to stay above it.
   DO NOT go back to a z-index:0 grain plus a `position: relative` sweep over
   main/header/footer/bars to out-stack it: that sweep silently overrode
   `position: fixed` on .quickbar and .mobile-cta (measured bottom: 6832px --
   pinned to the end of the document instead of the viewport) and would have
   flattened the transparent over-hero header too. */
body::after {
  content: ""; position: fixed; inset: 0; pointer-events: none;
  z-index: var(--z-overlay);
  opacity: .028;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---- Field polish: a valid field earns a quiet accent tick --------------- */
.field input:not(:placeholder-shown):valid,
.field select:valid:not([value=""]) { border-color: #9AA79B; }

/* ---- Card lift — shadow only, never a transform that shifts layout ------ */
.market { transition: box-shadow var(--t-mid) var(--ease), border-color var(--t-mid) var(--ease); }
.market:hover { box-shadow: var(--shadow-lg); }

/* ==========================================================================
   Reduced motion — everything above degrades to a static, fully visible page
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .hero__media--kenburns img { animation: none; }
  .stagger > * { opacity: 1; transform: none; animation: none; }
  .reveal--mask img { clip-path: none; transform: none; transition: none; }
  .quickbar { transition: none; }
  .btn--primary::after { display: none; }
  .scroll-progress { display: none; }
}

/* ---- Lockup width -------------------------------------------------------
   Sized for "Kelly Scalone" over "RE/MAX Services" -- both short, so this is
   back near the original 20rem rather than the 27rem the sister site needed
   for "RE/MAX Services".

   If the firm name ever lengthens (a co-branded office DBA, say), WIDEN the
   lockup rather than shrinking the firm text: .lockup__name and .lockup__firm
   must keep an identical font-size under FL 61J2-10.025, so type size is not
   an available lever here. */
.site-header .lockup { max-width: clamp(12rem, 26vw, 21rem); }

/* ---- Header balance at the longer firm name -----------------------------
   Measured at 1440px: the 7-item nav wants ~911px and the lockup wants 305px,
   which together exceed the 1248px inner width. Both are `flex: 0 1 auto`, so
   BOTH were shrinking and the firm name wrapped to three lines (header 144px).
   Raising max-width alone did nothing -- shrink, not max-width, was binding.
   Fix the real cause: stop the lockup shrinking, and buy the nav its space
   back by tightening its gap and tracking rather than dropping any link. */
.site-header .lockup { flex: 0 0 auto; }
.nav { gap: clamp(.7rem, 1.35vw, 1.2rem); }
.nav a { letter-spacing: .06em; }

/* ==========================================================================
   MOTION SYSTEM v2 — added 2026-07-30
   Vocabulary harvested from the factory's richest build
   (outputs/achasta_co_factory/home_v3.html) and extended with techniques that
   are effectively absent from residential real estate sites.

   Three rules govern everything below:
     1. Every effect is transform/opacity/filter only -- no layout-affecting
        property is ever animated, so CLS stays at 0.
     2. Every effect is additive. If the browser lacks the feature, or the
        visitor asks for reduced motion, the page renders as the static
        version that already passed QA.
     3. Nothing here touches .lockup__name / .lockup__firm sizing (FL
        61J2-10.025 parity) or any contrast pairing from tokens.css.
   ========================================================================== */

/* ---- 1. Cross-document view transitions ---------------------------------
   Navigation between pages cross-fades and the header persists instead of the
   page blinking white. Practically no real estate site does this; it is what
   makes the site feel like an application rather than a set of documents.
   Progressive by definition -- unsupported browsers just navigate normally. */
@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root) { animation-duration: .32s; animation-timing-function: cubic-bezier(.16,1,.3,1); }

/* The header and the sticky bars are the same object across pages, so name
   them and let the browser morph rather than cross-fade them. */
.site-header { view-transition-name: site-header; }
.mobile-cta  { view-transition-name: mobile-cta; }

/* ---- 2. Scroll-driven hero -----------------------------------------------
   The hero photograph scales and drifts, and the copy lifts away, driven by
   SCROLL POSITION rather than a timer -- so the motion tracks the visitor's
   thumb exactly. Runs entirely on the compositor thread (no scroll listener,
   no layout work). @supports means browsers without scroll-driven animation
   keep the existing 28s kenburns drift instead. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero__media--kenburns img,
    .hero .hero__media img {
      animation: heroScrollZoom linear both;
      animation-timeline: scroll(root);
      animation-range: 0vh 110vh;
    }
    .hero__inner > *, .lp-hero__inner > .stagger {
      animation: heroScrollLift linear both;
      animation-timeline: scroll(root);
      animation-range: 30vh 95vh;
    }
  }
}
@keyframes heroScrollZoom {
  from { transform: scale(1.02) translateY(0); }
  to   { transform: scale(1.16) translateY(-5%); }
}
@keyframes heroScrollLift {
  0%, 45% { opacity: 1; transform: translateY(0); }
  100%    { opacity: 0; transform: translateY(-38px); }
}

/* ---- 3. Kinetic headline ------------------------------------------------
   Each line rises out of its own mask on a stagger. The lines are real markup
   (not JS-split), so the h1 keeps its exact text for search engines and
   screen readers whether or not scripting runs. */
.kinetic { overflow: hidden; }
.kinetic__line { display: block; overflow: hidden; padding-bottom: .06em; }
.kinetic__line > span,
.kinetic__line > em {
  display: block;
  transform: translateY(108%);
  animation: kineticRise 1.05s cubic-bezier(.16,1,.3,1) forwards;
}
.kinetic__line:nth-child(1) > * { animation-delay: .10s; }
.kinetic__line:nth-child(2) > * { animation-delay: .22s; }
.kinetic__line:nth-child(3) > * { animation-delay: .34s; }
.kinetic__line:nth-child(4) > * { animation-delay: .46s; }
@keyframes kineticRise { to { transform: translateY(0); } }

/* ---- 4. Rule draw -------------------------------------------------------- */
.rm-bar, .trustbar { --draw: 1; }
.reveal .rm-bar,
.rule--draw { transform: scaleX(0); transform-origin: left center; }
.reveal.is-in .rm-bar,
.rule--draw.is-in { transform: scaleX(1); transition: transform 1.1s cubic-bezier(.16,1,.3,1); }

/* ---- 5. Scroll cue ------------------------------------------------------- */
.scrollcue {
  position: absolute; left: var(--gutter); bottom: clamp(1.25rem, 3vw, 2.25rem);
  z-index: var(--z-raised);
  display: flex; align-items: center; gap: var(--s-4);
  font-size: var(--fs-micro); font-weight: 600;
  letter-spacing: var(--ls-eyebrow); text-transform: uppercase;
  color: rgba(255,255,255,.82);
  opacity: 0; animation: riseIn 1s var(--ease-out) 1.25s forwards;
}
.scrollcue::after {
  content: ""; width: 1px; height: 3.25rem;
  background: linear-gradient(180deg, var(--rm-red-lift), transparent);
  animation: cuePulse 2.4s ease-in-out infinite;
}
@keyframes cuePulse {
  0%, 100% { opacity: .55; transform: scaleY(1); transform-origin: top; }
  50%      { opacity: 1;   transform: scaleY(1.18); transform-origin: top; }
}
@media (max-width: 900px) { .scrollcue { display: none; } }

/* ---- 6. Marquee band ----------------------------------------------------
   A slow editorial band of the streets and communities actually covered. Set
   in the display face so it reads as typography, not a ticker widget. */
.marquee {
  background: var(--rm-blue-ink); color: var(--mist);
  border-top: 1px solid rgba(255,255,255,.10);
  border-bottom: 1px solid rgba(255,255,255,.10);
  padding: clamp(1.5rem, 3vw, 2.75rem) 0;
  overflow: hidden; position: relative;
}
.marquee__track {
  display: flex; gap: clamp(2rem, 4vw, 4rem); width: max-content;
  animation: marqueeScroll 46s linear infinite; will-change: transform;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__item {
  font-family: var(--font-display); font-style: italic; font-weight: 400;
  font-size: clamp(1.15rem, 2.4vw, 2rem); line-height: 1.2;
  white-space: nowrap; display: inline-flex; align-items: center;
  gap: clamp(2rem, 4vw, 4rem); color: var(--mist);
}
.marquee__sep { color: var(--rm-red-lift); font-style: normal; }
@keyframes marqueeScroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ---- 7. Pointer spotlight on dark panels --------------------------------
   A soft warm light follows the cursor across the dark sections. --mx/--my
   are written by site.js at pointer-move; with no JS the gradient simply
   stays centred and reads as a static vignette. */
.section--dark, .section--ink { position: relative; isolation: isolate; }
.section--dark::before, .section--ink::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(
    38rem 38rem at var(--mx, 50%) var(--my, 40%),
    rgba(201,165,95,.13), transparent 68%);
  opacity: 0; transition: opacity var(--t-slow) var(--ease);
}
.section--dark.is-lit::before, .section--ink.is-lit::before { opacity: 1; }

/* ---- 8. Tilt on the market cards ----------------------------------------
   The photograph tilts inside its frame, not the whole card -- the card keeps
   its existing grid-breaking translateY offset, which a transform on .market
   itself would have destroyed. */
.market { perspective: 1000px; }
.market__media {
  transform: rotateX(var(--tiltX, 0deg)) rotateY(var(--tiltY, 0deg));
  transform-style: preserve-3d;
  transition: transform var(--t-mid) var(--ease-out);
}
.market__media::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(
    var(--sheen, 120deg),
    rgba(255,255,255,.16), transparent 42%);
  opacity: 0; transition: opacity var(--t-mid) var(--ease);
}
.market:hover .market__media::after { opacity: 1; }

/* ---- 9. Magnetic CTAs ---------------------------------------------------
   The button leans a few pixels toward the cursor as it approaches. Applied
   via translate on a CHILD-free transform so nothing around it reflows; the
   displacement is capped at 6px, which reads as responsiveness rather than
   as a moving target that is hard to click. */
.btn { will-change: transform; }
.btn[data-magnetic] {
  transform: translate(var(--magX, 0px), var(--magY, 0px));
  transition: transform 220ms cubic-bezier(.16,1,.3,1),
              background-color var(--t-mid) var(--ease),
              color var(--t-mid) var(--ease),
              border-color var(--t-mid) var(--ease),
              box-shadow var(--t-mid) var(--ease);
}

/* ==========================================================================
   Article prose (Inside the Gates)
   A measure of ~68ch, not the full wrap: long-form reading is the one place on
   this site where line length matters more than the grid. Headings stay in the
   display face so a post still reads as part of the same publication.
   ========================================================================== */
/* Scoped to .prose--article, NOT to .prose. `.prose` already exists further up
   (line ~540) and is what /privacy/ uses; redefining it here silently restyled
   the privacy policy -- different measure, different heading scale, underlined
   links. Articles opt in with an extra class instead, so the shared rules keep
   doing exactly what they did before. */
.prose--article { max-width: 44rem; }
.prose--article > h2 {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  line-height: 1.18;
  margin: var(--s-8) 0 var(--s-4);
}
.prose--article > h2:first-of-type { margin-top: var(--s-7); }
.prose--article > p { max-width: 68ch; margin: 0 0 var(--s-4); }
.prose--article > ul { margin: var(--s-5) 0 var(--s-6); }
.prose--article a { color: inherit; text-decoration: underline; text-underline-offset: .18em;
           text-decoration-thickness: 1px; text-decoration-color: var(--rm-red-ink); }
.prose--article a:hover { text-decoration-thickness: 2px; }

.prose__intro { font-size: var(--fs-lead); line-height: 1.5; color: var(--rm-blue-ink); }
.prose__byline {
  font-size: var(--fs-micro); letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 var(--s-3);
}
.prose__byline span { text-transform: none; letter-spacing: 0; }

/* A standing caveat, not a decorative pull-quote. Used where a post describes
   a statute that has been amended and could be amended again -- the reader
   needs to see that before the detail, not in a footnote. */
.prose__note {
  border-left: 3px solid var(--rm-red-ink);
  background: var(--mist, rgba(0,0,0,.03));
  padding: var(--s-4) var(--s-5);
  margin: var(--s-6) 0;
  font-size: var(--fs-small);
}

/* The post hero carries a headline that is a QUESTION, so it runs longer than
   the display lines elsewhere. Cap it rather than letting it fill the viewport. */
.hero--post .hero__title { font-size: clamp(2rem, 4.4vw, 3.4rem); max-width: 20ch; }
.hero--post .hero__lead { max-width: 56ch; }

/* ---- 10. Grain upgraded to overlay blend --------------------------------- */
body::after { mix-blend-mode: overlay; opacity: .05; }

/* ---- 11. Horizontal snap strip on small screens -------------------------
   Below 900px the four market cards already stack. A snap rail turns that
   dead vertical scroll into a deliberate swipe through the four towns. */
@media (max-width: 900px) {
  .markets {
    grid-auto-flow: column;
    grid-template-columns: none;
    grid-auto-columns: 78%;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    gap: var(--s-4);
    padding-bottom: var(--s-4);
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    scrollbar-width: none;
  }
  .markets::-webkit-scrollbar { display: none; }
  .markets .market { scroll-snap-align: start; }
}

/* ==========================================================================
   Reduced motion — the whole system above collapses to the static page
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .kinetic__line > span, .kinetic__line > em { transform: none; animation: none; }
  .marquee__track { animation: none; }
  .scrollcue::after { animation: none; }
  .market__media { transform: none; transition: none; }
  .btn[data-magnetic] { transform: none; }
  .section--dark::before, .section--ink::before { display: none; }
  .reveal .rm-bar, .rule--draw { transform: none; }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

/* ==========================================================================
   PORTRAIT LAYER — added 2026-08-05
   Kelly's own photography, wired in as composition rather than as "a photo of
   the agent" dropped into a box. Five components:

     .hero__figure   the standing cutout in the home hero
     .pframe         a framed editorial portrait with a caption
     .pgallery       the asymmetric portrait set on /about/
     .agentbar       the who-you-are-dealing-with byline card
     .sigquote       pull quote set beside a portrait

   Rules this layer keeps, same as the layers above it:
     1. Additive only. Nothing here redefines a base component, so deleting
        this block returns the site to the state that already passed QA.
     2. Nothing sets a font-size on .lockup__name / .lockup__firm, so the
        agent's name stays at parity with the brokerage name (FL 61J2-10.025).
        A PHOTOGRAPH is not name typography and its size is unconstrained;
        what the rule forbids is her NAME set larger than the firm's.
     3. Only transform/opacity/filter animate, so CLS stays 0.
   ========================================================================== */

/* ---- 1. The standing figure in the hero ---------------------------------
   She is bottom-anchored to the hero's lower edge so she stands ON the
   composition; the .overlap panel that follows then crosses in FRONT of her at
   z-index 10, which is what makes the hero read as layered depth instead of a
   flat photo with a person pasted on it.

   Desktop only, deliberately. At 390px a full-length figure either shrinks to
   an unreadable 90px or forces the headline across her face. Both are worse
   than .hero__chip below, which puts her face on mobile at a size that can
   actually be seen. */
.hero--figure { overflow: hidden; }

.hero__figure {
  position: absolute;
  /* Tied to the CONTENT column, not the viewport edge. Pinned to the viewport
     she measured 598px away from the copy at 1920 and read as a lone cut-out
     in the corner; anchoring to the wrap's right edge (with a 2rem bleed
     outside it, which is the editorial part) keeps her and the headline reading
     as one composition at every width. */
  right: max(1.25vw, calc((100% - var(--maxw)) / 2 - 2rem));
  bottom: 0;
  z-index: 0;
  margin: 0;
  display: none;                     /* enabled at >=900px, below */
  /* 82vh, not 72vh: the hero is min(88vh, 900px) tall, so at 72vh she was
     277px wide and undersized against a 4rem headline. */
  height: clamp(28rem, 82vh, 48rem);
  aspect-ratio: 562 / 1313;
  pointer-events: none;              /* never steals a click from the CTA */
}
.hero__figure img {
  width: 100%; height: 100%;
  object-fit: contain; object-position: bottom center;
  /* Directional shadow matching the scrim's light direction. Without it a
     transparent cutout floats; with it she occupies the same space as the
     photograph behind her. */
  filter: drop-shadow(-26px 16px 40px rgba(3, 10, 20, .55));
}
/* Warm halo, so she is grounded in the palette and not just keyed out. */
.hero__figure::before {
  content: ""; position: absolute; inset: 10% -26% -4% -34%; z-index: -1;
  background: radial-gradient(56% 50% at 54% 76%,
              rgba(201, 165, 95, .22), rgba(201, 165, 95, 0) 70%);
}

@media (min-width: 900px) {
  .hero--figure .hero__figure { display: block; }
  /* The base .hero__inner is a 7fr/5fr grid because the facts block used to
     occupy the right column. Here the figure owns that side, so the copy gets
     one full-width column and is then capped by max-width -- otherwise the
     percentage cap below would resolve against the 7fr track and squeeze the
     headline to ~35% of the page. */
  .hero--figure .hero__inner { grid-template-columns: minmax(0, 1fr); }
  /* The copy can never run under her: the figure is ~19rem wide at its
     tallest, so the text column is capped well clear of it. */
  .hero--figure .hero__copy { max-width: min(38rem, 60%); }
}

/* Facts strip. On the home hero the brokerage line and direct line move out of
   the right column (the figure owns that side now) and sit under the copy as a
   horizontal strip. FL 61J2-10.025 is satisfied exactly as before: the firm
   name stays immediately adjacent to the phone number. */
/* Wider than the copy on purpose. These are three short label/value pairs; at
   the copy's 38rem cap the first value wrapped to THREE lines and broke
   mid-phrase ("Delray Beach, Boca / Raton / & Palm Beach Gardens"), which is why
   the strip is a sibling of .hero__copy rather than a child of it. */
@media (min-width: 900px) {
  .hero--figure .hero__facts { max-width: min(46rem, 68%); }
}
.hero__facts {
  margin: var(--s-7) 0 0; padding-top: var(--s-5);
  border-top: 1px solid rgba(201, 165, 95, .45);
  display: grid; grid-template-columns: repeat(3, auto);
  justify-content: start; gap: var(--s-5) clamp(1.5rem, 4vw, 3.25rem);
}
.hero__facts dt {
  font-size: var(--fs-micro); letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase; color: var(--rm-red-lift); font-weight: 600;
  margin-bottom: .2rem;
}
.hero__facts dd {
  margin: 0; color: var(--white); font-family: var(--font-display);
  font-size: 1.2rem; line-height: 1.25;
}
@media (max-width: 700px) {
  .hero__facts { grid-template-columns: 1fr 1fr; gap: var(--s-4) var(--s-5); }
}

/* Mobile face — a real portrait at a size that reads. */
/* Shown at EVERY width. It was mobile-only on the sister site, where a
   full-length cutout owned the desktop hero; this site has no such photograph
   (scripts/prep_portraits.py), so the chip is the only face in the hero and
   hiding it above 899px left the hero with none at all. If a real shoot ever
   restores .hero__figure, put the `display: none` back in the same change --
   otherwise the chip and the cutout both render. */
.hero__chip {
  display: flex; align-items: center; gap: var(--s-4); margin-top: var(--s-6);
}
.hero__chip img {
  width: 68px; height: 68px; flex: 0 0 auto; border-radius: var(--r-pill);
  /* The RE/MAX red ring, not the sister site's brass. Decorative, so the 3:1
     non-text floor is what applies, and red on the scrimmed photo clears it. */
  border: 2px solid rgba(220, 28, 46, .85);
  box-shadow: 0 6px 18px rgba(3, 10, 20, .45);
}
.hero__chip b {
  display: block; font-family: var(--font-display); font-weight: 700;
  font-size: 1.2rem; color: var(--white); line-height: 1.2;
  letter-spacing: -0.01em;
}
.hero__chip span {
  display: block; font-size: var(--fs-micro); letter-spacing: .06em;
  color: rgba(255, 255, 255, .78);
}
@media (min-width: 900px) {
  /* Slightly larger where there is room, and nudged off the copy block. */
  .hero__chip { margin-top: var(--s-7); }
  .hero__chip img { width: 76px; height: 76px; }
}

}

/* ---- 2. Framed editorial portrait ---------------------------------------
   The same offset accent rule as .split__media, plus a caption. The caption
   earns its place: it is where the brokerage line sits beside her face. */
.pframe { position: relative; margin: 0; }
.pframe img { width: 100%; box-shadow: var(--shadow-lg); }
/* TOP-corner bracket, not bottom.
   .split__media puts this bracket at the bottom-left, but that element has no
   caption. Here the pseudo-element is positioned against the whole <figure>,
   which INCLUDES the figcaption -- so a bottom-anchored bracket drew its
   horizontal rule underneath the caption text and read as a stray underline
   rather than a frame offset behind the photograph. Anchoring to the top corner
   is caption-height-independent, so it cannot regress when a caption wraps. */
.pframe::before {
  content: ""; position: absolute; inset: -14px auto auto -14px;
  width: 58%; height: 42%; z-index: -1;
  border-left: 2px solid var(--rm-red-ink); border-top: 2px solid var(--rm-red-ink);
}
.pframe--right::before {
  inset: -14px -14px auto auto;
  border-left: 0; border-right: 2px solid var(--rm-red-ink);
}
.pframe figcaption {
  margin-top: var(--s-4); padding-left: var(--s-3);
  border-left: 2px solid var(--rm-red-ink);
  font-size: var(--fs-micro); letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); line-height: 1.5;
}
.section--dark .pframe::before, .section--ink .pframe::before,
.on-dark .pframe::before { border-color: var(--rm-red-lift); }
.section--dark .pframe figcaption, .section--ink .pframe figcaption,
.on-dark .pframe figcaption {
  border-left-color: var(--rm-red-lift); color: rgba(228, 220, 205, .82);
}

/* ---- 3. Portrait set — REMOVED 2026-08-06 -------------------------------
   .pgallery was the /about/ 3-up. Its `@media (max-width:760px)` collapse to a
   single column is precisely what stacked two near-identical poolside frames
   directly on top of each other on a phone. /about/ now runs one portrait in a
   .split, so the grid has no remaining user and is deleted rather than left
   for someone to reach for again. The rule it enforced lives in
   scripts/prep_portraits.py: one source frame, one display surface. */

/* ---- 4. Agent byline card ------------------------------------------------
   Used on the conversion pages. A face beside the licence number and the
   direct line: a trust surface and a compliance surface at once. */
/* Vertical padding raised 2026-08-06 (was clamp(1.1rem, 2.6vw, 1.6rem), i.e.
   25.6px at desktop). Measured on /selling/ at 1440px before the change: the
   card was 138px tall with 25.6px of padding top and bottom, leaving 86.8px of
   content height around an 84px portrait circle -- 1.4px of clearance per side.
   The circle therefore spanned essentially the entire inner height of the card
   and read as jammed in rather than placed in it, which is what Bryan saw.

   The lever is the PADDING, not the circle or the copy. Shrinking the circle
   would weaken the one thing this card exists to do (put a face beside the
   licence number), and cutting a line of copy would remove compliance text.
   Raising the padding to 36px at desktop puts the clearance at ~37px per side.
   The horizontal value is deliberately left alone -- it was never the problem,
   and changing it would shift the text column for no reason. */
.agentbar {
  display: flex; align-items: center; gap: clamp(1rem, 2.5vw, 1.75rem);
  background: var(--paper); box-shadow: var(--shadow-md);
  border-top: 3px solid var(--rm-red-ink);
  padding: clamp(1.6rem, 3.4vw, 2.25rem) clamp(1.1rem, 2.6vw, 1.9rem);
}
.agentbar__img {
  flex: 0 0 auto; width: 84px; height: 84px; border-radius: var(--r-pill);
  overflow: hidden; box-shadow: var(--shadow-sm);
}
.agentbar__img img { width: 100%; height: 100%; object-fit: cover; }
.agentbar__name {
  font-family: var(--font-display); font-size: 1.35rem; line-height: 1.2;
  color: var(--rm-blue); margin: 0 0 .15rem;
}
.agentbar__meta {
  margin: 0; font-size: var(--fs-micro); color: var(--muted);
  line-height: 1.55; max-width: none;
}
.agentbar__call { margin-left: auto; flex: 0 0 auto; }
@media (max-width: 700px) {
  .agentbar { flex-wrap: wrap; }
  .agentbar__img { width: 64px; height: 64px; }
  .agentbar__call { margin-left: 0; width: 100%; }
}

/* ---- 5. Signature quote -------------------------------------------------- */
/* padding-top is s-7, not s-6: at s-6 the oversized opening quote glyph rode up
   into the eyebrow above it and the two collided. */
.sigquote {
  position: relative; padding-top: var(--s-7);
  font-family: var(--font-display); font-size: var(--fs-h2);
  line-height: 1.24; letter-spacing: var(--ls-display);
  color: var(--white); max-width: 30ch; margin: 0 0 var(--s-5);
}
.sigquote::before {
  content: "\201C"; position: absolute; top: -.12em; left: -.06em;
  font-size: 4.5rem; line-height: 1; color: var(--rm-red-lift); opacity: .55;
}
.sigattr {
  font-family: var(--font-body); font-size: var(--fs-micro);
  letter-spacing: var(--ls-eyebrow); text-transform: uppercase;
  color: var(--rm-red-lift); font-weight: 600;
}

/* ---- 6. Motion ----------------------------------------------------------
   She rises in on load, then settles down behind the .overlap panel as the
   page scrolls. Two elements carry the two animations (wrapper = scroll-driven,
   img = entrance) so neither overwrites the other's transform. */
@keyframes figureIn {
  from { opacity: 0; transform: translateY(30px) scale(.995); }
  to   { opacity: 1; transform: none; }
}
@keyframes figureSettle {
  from { transform: translateY(0); opacity: 1; }
  to   { transform: translateY(26px); opacity: .9; }
}
@media (prefers-reduced-motion: no-preference) {
  .hero__figure img { animation: figureIn 900ms var(--ease-out) 220ms both; }
  @supports (animation-timeline: scroll()) {
    .hero__figure {
      animation: figureSettle linear both;
      animation-timeline: scroll(root);
      animation-range: 0vh 100vh;
    }
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero__figure, .hero__figure img { animation: none; transform: none; opacity: 1; }
  .pgallery > :first-child { transform: none; }
}
