/* ===========================================================================
   Ryth Vara — Pennsylvania Real Estate

   The palette comes from Pennsylvania building materials rather than from the
   usual luxury-realtor kit: bluestone, slate roofs, fieldstone, and the aged
   brass on old front doors. A dark page lets the hero footage be the light
   source — the house glows out of the slate instead of sitting on white.

   Type is Fraunces for display and Archivo for everything else. Fraunces
   carries an optical-size axis, so headings get the chiselled, high-contrast
   cut and small text stays readable, from one file.
   ======================================================================== */

:root {
  --slate:      #12171c;
  --slate-2:    #191f26;
  --slate-3:    #222a33;
  --bluestone:  #2c3e4a;
  --brass:      #b08d57;
  --brass-lt:   #d4b483;
  --ivory:      #f2eee7;
  --ivory-dim:  #a8afb6;

  --border:     rgba(242, 238, 231, 0.12);
  --border-lit: rgba(176, 141, 87, 0.42);

  --font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --font-body: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --wrap: 78rem;
  --gutter: clamp(1.25rem, 5vw, 4rem);

  /* Vertical rhythm. Sections share one scale so spacing never drifts.
     Two sections meet with this twice (bottom of one, top of the next), so
     it is kept modest: about 11rem between sections on a laptop, 6.5rem on
     a phone. */
  --space-section: clamp(3.25rem, 6.5vw, 5.5rem);

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

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

html {
  scroll-behavior: smooth;
  /* The stage is position:sticky; a scroll-padding keeps in-page anchors from
     landing under it. */
  scroll-padding-top: 2rem;
}

body {
  margin: 0;
  background: var(--slate);
  color: var(--ivory);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

a { color: var(--brass-lt); }

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

/* One focus treatment everywhere, and it is never removed. */
:focus-visible {
  outline: 2px solid var(--brass-lt);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -120%);
  z-index: 50;
  padding: 0.75rem 1.25rem;
  background: var(--brass);
  color: var(--slate);
  font-weight: 600;
  text-decoration: none;
  transition: transform 0.18s var(--ease);
}
.skip-link:focus { transform: translate(-50%, 0); }

.wrap {
  width: min(var(--wrap), 100%);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ============================ Scroll stage ============================== */

.stage {
  /* Set by stage.js — 209 normally, 100 when reduced motion is requested.
     The fallback only applies for the instant before that script runs, but it
     is kept in step so the page never reflows from a stale value. */
  height: calc(var(--stage-vh, 209) * 1vh);
  position: relative;
}

.stage__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  display: grid;
  place-items: center;
  /* Visible before the first frame lands, and behind the feathered bottom edge
     of the footage. */
  background:
    radial-gradient(120% 90% at 50% 18%, var(--slate-3) 0%, var(--slate) 62%);
}

.stage__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 0.7s var(--ease);
}
.stage__canvas.is-ready { opacity: 1; }

.stage__title {
  position: relative;
  z-index: 2;
  text-align: center;
  padding-inline: var(--gutter);
  /* Sits in the upper third, over the dark treeline rather than across the
     lit facade: better contrast for the type, and it stops covering the
     subject of the shot. */
  transform: translateY(-15vh);
  will-change: opacity, transform;
}

.stage__name {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 144;
  font-weight: 400;
  font-size: clamp(3rem, 13vw, 10.5rem);
  line-height: 0.92;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0;
  color: var(--ivory);
  text-shadow: 0 0.15em 1.2em rgba(0, 0, 0, 0.55);
}

.stage__tagline {
  display: block;
  font-family: var(--font-body);
  font-variation-settings: normal;
  line-height: 1.6;
  font-size: clamp(0.72rem, 1.5vw, 0.95rem);
  letter-spacing: 0.42em;
  text-indent: 0.42em; /* offsets the trailing letter-space so it stays centred */
  text-transform: uppercase;
  color: var(--ivory);
  margin: 1.1rem 0 0;
  text-shadow: 0 0.1em 0.8em rgba(0, 0, 0, 0.6);
}

/* Hairline that fills as the frame sequence loads, so the one decorative-
   looking element on the hero is actually reporting something. */
.stage__rule {
  width: min(22rem, 60vw);
  height: 1px;
  margin: 2.1rem auto 0;
  background: rgba(242, 238, 231, 0.22);
  overflow: hidden;
}
.stage__rule-fill {
  display: block;
  height: 100%;
  background: var(--brass-lt);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s linear, opacity 0.8s var(--ease) 0.3s;
}
.stage__rule-fill.is-complete { opacity: 0; }

.stage__cue {
  position: absolute;
  z-index: 2;
  bottom: clamp(1.5rem, 4vh, 3rem);
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  font-size: 0.68rem;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-transform: uppercase;
  color: var(--ivory-dim);
  /* Opacity is driven by stage.js alongside the title. */
  will-change: opacity;
}

/* The link to the same page in the other language (Español / English), top
   right over the hero. Square corners and a brass hairline, like the buttons. */
.lang-switch {
  position: absolute;
  z-index: 3;
  top: clamp(0.75rem, 2.5vh, 1.5rem);
  right: var(--gutter);
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0 1rem;
  border: 1px solid var(--border-lit);
  background: rgba(18, 23, 28, 0.6);
  color: var(--ivory);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  transition: border-color 0.22s var(--ease), color 0.22s var(--ease);
}
.lang-switch:hover,
.lang-switch:focus-visible { border-color: var(--brass); color: var(--brass-lt); }

/* Without WebGL the canvas is the raw frame buffer at its native size and the
   shader's work has to be done in CSS: cover-fit so the footage is not
   stretched to the viewport's aspect, and a scrim so the title stays legible
   over the bright facade. Opacity tracks --title-opacity, set by stage.js, so
   it fades in step with the title exactly as the shader version does. */
.no-webgl .stage__canvas {
  object-fit: cover;
}
.no-webgl .stage__sticky::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: var(--title-opacity, 1);
  background:
    radial-gradient(58% 34% at 50% 34%, rgba(6, 9, 12, 0.82) 0%, rgba(6, 9, 12, 0) 100%),
    linear-gradient(rgba(6, 9, 12, 0.38), rgba(6, 9, 12, 0.38));
}

/* ============================== Sections =============================== */

.section { padding-block: var(--space-section); }

.section__title {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 96;
  font-weight: 400;
  font-size: clamp(2rem, 5.2vw, 4rem);
  line-height: 1.04;
  letter-spacing: -0.015em;
  margin: 0 0 clamp(1.75rem, 3.5vw, 2.75rem);
  max-width: 20ch;
  text-wrap: balance;
}

.lede {
  font-size: clamp(1.1rem, 1.9vw, 1.35rem);
  line-height: 1.5;
  color: var(--ivory);
}

.discover p { max-width: 62ch; color: var(--ivory-dim); }
.discover p strong { color: var(--ivory); font-weight: 600; }

/* The Discover text, built to be read at a glance: one line, three numbers,
   three specialties, one short paragraph. */
.discover .discover__lede {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 36;
  font-size: clamp(1.35rem, 2.4vw, 1.75rem);
  line-height: 1.35;
  color: var(--ivory);
  max-width: 32ch;
  margin: 0 0 2.25rem;
}
.discover__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.25rem;
  list-style: none;
  padding: 0;
  margin: 0 0 2.25rem;
}
.discover__stats li { border-top: 1px solid var(--border-lit); padding-top: 1rem; }
.discover__num {
  display: block;
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 96;
  font-size: clamp(2.1rem, 4.5vw, 3rem);
  line-height: 1;
  color: var(--ivory);
}
.discover__cap { display: block; margin-top: 0.55rem; font-size: 0.85rem; line-height: 1.4; color: var(--ivory-dim); }
.discover__tags { display: flex; flex-wrap: wrap; gap: 0.6rem; list-style: none; padding: 0; margin: 0 0 1.75rem; }
.discover__tags li {
  border: 1px solid var(--border-lit);
  border-radius: 999px;
  padding: 0.5rem 1rem;
  font-size: 0.88rem;
  color: var(--ivory);
}

.discover__grid {
  display: grid;
  gap: clamp(2rem, 5vw, 4.5rem);
  grid-template-columns: 1fr;
}

.discover__portrait img {
  width: 100%;
  /* height:auto is load-bearing. The width/height attributes on the <img> are
     there to reserve space, but they also set a presentational height of
     800px, and aspect-ratio is ignored whenever both dimensions are specified.
     Without this the portrait rendered 800px tall at every width. */
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  background: var(--slate-2);
  border: 1px solid var(--border);
}

/* Contact details beside the portrait (factsHTML in render.js). One set of
   HTML, two looks. On a phone: three buttons (call or text, email,
   directions), then the office, hours and languages on one line. From tablet
   width up: a tile for each detail. */
.contact {
  display: block;
  margin: clamp(1.75rem, 4vw, 2.5rem) 0;
  font-style: normal;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--ivory-dim);
}
.contact__item { text-decoration: none; }
.contact__icon { display: inline-grid; place-items: center; flex: none; }
.contact__icon svg { width: 1.1rem; height: 1.1rem; }

/* Phone: the three buttons. */
.contact__item--call,
.contact__item--email,
.contact__item--directions {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  min-height: 2.9rem;
  margin: 0 0 0.75rem;
  padding: 0.55rem 1.15rem;
  border: 1px solid var(--brass);
  color: var(--brass-lt);
  font-weight: 600;
  line-height: 1.3;
  overflow-wrap: anywhere;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.contact__item--call { background: var(--brass); color: var(--slate); }
.contact__item--call:hover,
.contact__item--call:focus-visible { background: var(--brass-lt); border-color: var(--brass-lt); }
.contact__item--email:hover,
.contact__item--email:focus-visible,
.contact__item--directions:hover,
.contact__item--directions:focus-visible { background: var(--brass); color: var(--slate); }

/* Phone: the line under the buttons, "Office: … · Open 24/7 · English and
   Español". Labels the line does not show stay readable by screen readers. */
.contact__item--office,
.contact__item--hours,
.contact__item--languages { display: inline; }
.contact__item--office .contact__icon,
.contact__item--hours .contact__icon,
.contact__item--languages .contact__icon { display: none; }
.contact__item--office .contact__label { color: var(--ivory); font-weight: 600; }
.contact__item--office .contact__label::after { content: ':'; content: ':' / ''; }
.contact__item--hours .contact__value { color: var(--ivory); font-weight: 600; }
.contact__item--hours::before,
.contact__item--languages::before { content: ' · '; content: ' · ' / ''; }
.contact__item--email .contact__label,
.contact__item--hours .contact__label,
.contact__item--languages .contact__label {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Tablet and up: tiles. Call and email side by side, the office across the
   full width (the whole tile opens directions), then hours and languages. */
@media (min-width: 48rem) {
  .contact {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-areas:
      "call email"
      "office office"
      "hours languages";
    gap: 0.75rem;
    font-size: 1rem;
    line-height: 1.4;
  }
  .contact__item,
  .contact__item--office,
  .contact__item--hours,
  .contact__item--languages {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    min-width: 0;
    min-height: 0;
    margin: 0;
    padding: 0.95rem 1.1rem;
    border: 1px solid var(--border);
    background: var(--slate-2);
    color: var(--ivory);
    font-weight: 400;
    transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease);
  }
  .contact__item--call { grid-area: call; }
  .contact__item--email { grid-area: email; }
  .contact__item--office { grid-area: office; padding-right: 13rem; }
  .contact__item--hours { grid-area: hours; }
  .contact__item--languages { grid-area: languages; }
  .contact__item--hours::before,
  .contact__item--languages::before { content: none; }

  a.contact__item:hover,
  a.contact__item:focus-visible { border-color: var(--border-lit); background: var(--slate-3); color: var(--ivory); }

  .contact__item--office .contact__icon,
  .contact__item--hours .contact__icon,
  .contact__item--languages .contact__icon,
  .contact__icon {
    display: grid;
    width: 2.6rem;
    height: 2.6rem;
    border: 1px solid var(--border-lit);
    border-radius: 50%;
    color: var(--brass-lt);
  }
  .contact__text { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
  .contact .contact__label {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    clip: auto;
    clip-path: none;
    white-space: normal;
    font-size: 0.72rem;
    font-weight: 400;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ivory-dim);
  }
  .contact__item--office .contact__label::after { content: none; }
  .contact .contact__value { color: var(--ivory); font-weight: 400; overflow-wrap: break-word; }

  /* "Get directions" lies over the office tile, so the whole tile is the
     link, with its words at the right. */
  .contact__item--directions {
    grid-area: office;
    position: relative;
    z-index: 1;
    justify-content: flex-end;
    border-color: transparent;
    background: transparent;
    color: var(--brass-lt);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
  }
  .contact__item--directions .contact__icon { display: none; }
  .contact__item--directions .contact__text { display: block; }
  .contact__item--directions .contact__text::after { content: ' \2192'; content: ' \2192' / ''; }
  a.contact__item--directions:hover,
  a.contact__item--directions:focus-visible { border-color: transparent; background: transparent; color: var(--brass-lt); }
  .contact__item--directions:hover + .contact__item--office,
  .contact__item--directions:focus-visible + .contact__item--office { border-color: var(--border-lit); background: var(--slate-3); }
}

.social {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  padding: 0;
  margin: 0 0 2rem;
}
.social__link {
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* =============================== Button ================================ */

.button {
  display: inline-block;
  padding: 0.95rem 2rem;
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid var(--brass);
  background: transparent;
  color: var(--brass-lt);
  cursor: pointer;
  transition: background-color 0.22s var(--ease), color 0.22s var(--ease);
}
.button--primary:hover,
.button--primary:focus-visible {
  background: var(--brass);
  color: var(--slate);
}
.button[disabled] { opacity: 0.5; cursor: not-allowed; }

/* ============================== Listings =============================== */

.listings__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem 2rem;
  flex-wrap: wrap;
}
/* Both carousels (listings and testimonials): the arrows sit on the title's
   line, not below it. */
.listings__head .section__title { margin-bottom: 0; }

.carousel__nav {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}
.carousel__status {
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ivory-dim);
  margin: 0 0.5rem 0 0;
}
.carousel__button {
  /* 44px minimum, so it is a real touch target. */
  width: 2.875rem;
  height: 2.875rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--border-lit);
  border-radius: 50%;
  background: transparent;
  color: var(--brass-lt);
  cursor: pointer;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease),
              opacity 0.2s var(--ease);
}
.carousel__button svg { width: 1.25rem; height: 1.25rem; }
.carousel__button:hover:not([disabled]),
.carousel__button:focus-visible:not([disabled]) {
  background: var(--brass);
  color: var(--slate);
}
.carousel__button[disabled] { opacity: 0.3; cursor: default; }

.carousel { margin-top: clamp(1.5rem, 3vw, 2.25rem); }

.carousel__track {
  display: grid;
  grid-auto-flow: column;
  /* Two cards per view on desktop, one on mobile — set in the media query. */
  grid-auto-columns: 100%;
  gap: clamp(1rem, 2.5vw, 2rem);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  /* The gap must not count toward a page, or paging drifts out of alignment. */
  padding-bottom: 0.5rem;
}
.carousel__track::-webkit-scrollbar { display: none; }

[data-carousel-item] {
  scroll-snap-align: start;
  min-width: 0;
}

.listing__frame {
  position: relative;
  overflow: hidden;
  background: var(--slate-2);
  border: 1px solid var(--border);
}
.listing__photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
.listing__status {
  position: absolute;
  top: 0.9rem;
  left: 0.9rem;
  padding: 0.35rem 0.7rem;
  background: var(--slate);
  color: var(--brass-lt);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.listing__body { padding-top: 1.25rem; }

.listing__address {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 48;
  font-weight: 400;
  font-size: clamp(1.25rem, 2.2vw, 1.6rem);
  line-height: 1.2;
  margin: 0;
}
.listing__city {
  margin: 0.3rem 0 0;
  color: var(--ivory-dim);
  font-size: 0.95rem;
}
.listing__price {
  margin: 0.9rem 0 0;
  color: var(--brass-lt);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.listing__reduced {
  margin: 0.3rem 0 0;
  color: var(--ivory-dim);
  font-size: 0.9rem;
}

.specs {
  display: flex;
  gap: 2rem;
  margin: 1.1rem 0 0;
  padding-top: 1.1rem;
  border-top: 1px solid var(--border);
}
.specs__item { display: flex; flex-direction: column-reverse; gap: 0.15rem; }
.specs__label {
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ivory-dim);
}
.specs__value {
  margin: 0;
  font-size: 1.35rem;
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 36;
  line-height: 1.1;
}

/* ============================ Testimonials ============================= */

/* Set as a pull quote rather than a card: the words are the content, so the
   type carries it and a single brass rule marks where the quote ends and the
   person begins. */
.quote {
  margin: 0;
  padding: clamp(1.75rem, 3vw, 2.5rem);
  background: var(--slate-2);
  border: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  height: 100%;
}

.quote__text {
  margin: 0;
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 40;
  font-weight: 400;
  font-size: clamp(1.1rem, 1.7vw, 1.35rem);
  line-height: 1.45;
  color: var(--ivory);
}
/* Hanging quote marks, so the first line still aligns with everything else. */
.quote__text::before { content: '\201C'; }
.quote__text::after  { content: '\201D'; }

/* The attribution sits directly under the quote rather than being pushed to
   the bottom of the card. Cards in a row still match height, but a short quote
   no longer leaves its name stranded below a gap. */
.quote__by {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border-lit);
  margin-bottom: auto;
}
.quote__name {
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass-lt);
}
.quote__detail {
  font-size: 0.88rem;
  color: var(--ivory-dim);
}

/* ============================== Contact ================================ */

/* The form is the whole section now — there is no aside beside it, so it
   spreads across the full measure instead of sharing the row. */
.contact__grid { display: block; }

.form {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}
.field--full { grid-column: 1 / -1; }

.field__label {
  display: block;
  /* 0.76rem x 1.3 — asked for deliberately, and the fields grew to match. */
  font-size: 0.99rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ivory-dim);
  margin-bottom: 0.55rem;
}

.field__input {
  width: 100%;
  padding: 1rem 1.15rem;
  font-family: var(--font-body);
  font-size: 1.1rem;
  color: var(--ivory);
  background: var(--slate-2);
  border: 1px solid var(--border);
  border-radius: 0;
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
  -webkit-appearance: none;
  appearance: none;
}
.field__input:hover { border-color: var(--bluestone); }
.field__input:focus { border-color: var(--brass); background: var(--slate-3); }
.field__input[aria-invalid='true'] { border-color: #e0785f; }
.field__input--area { resize: vertical; min-height: 11rem; }

.field__select { position: relative; }
.field__chevron {
  position: absolute;
  right: 1rem;
  top: 50%;
  transform: translateY(-50%);
  width: 1.1rem;
  height: 1.1rem;
  color: var(--ivory-dim);
  pointer-events: none;
}
.field__select .field__input { padding-right: 2.75rem; }

.field__hint,
.field__error { margin: 0.5rem 0 0; font-size: 0.92rem; }
.field__hint { color: var(--ivory-dim); }
.field__error { color: #e0785f; }
.field__error:empty { display: none; }

.form__actions {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin-top: 0.5rem;
}
/* 0.85rem x 1.3, to sit with the enlarged labels. Scoped to the form so the
   button in the bio section keeps its original size. */
.form .button {
  font-size: 1.1rem;
  padding: 1.15rem 2.75rem;
}
.form__result { margin: 0; font-size: 1.05rem; }
.form__result[data-state='success'] { color: var(--brass-lt); }
.form__result[data-state='error'] { color: #e0785f; }
.form__result[data-state='pending'] { color: var(--ivory-dim); }

/* Removed from view without display:none, which some bots treat as a signal
   to skip the field. */
.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* =============================== Footer ================================ */

.footer {
  border-top: 1px solid var(--border);
  padding-block: 2.5rem;
  color: var(--ivory-dim);
  font-size: 0.88rem;
}
.footer__inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: clamp(1.5rem, 4vw, 3rem);
  flex-wrap: wrap;
}
.footer p { margin: 0; }

.footer__brands {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2rem);
}
/* Sized by height, not width: the two marks have very different aspect ratios,
   so matching their optical weight means matching how tall they read. */
.footer__mark { width: auto; }
/* The Real lockup stacks a wordmark above the boxed logo, so it needs real
   height before that top line is readable at all. */
.footer__mark--team { height: 4.25rem; }
.footer__mark--broker { height: 4rem; }

.footer__divider {
  width: 1px;
  height: 3rem;
  background: var(--border);
}

.footer__legal { text-align: right; }
.footer__legal p + p { margin-top: 0.35rem; }

@media (max-width: 40rem) {
  .footer__inner { justify-content: center; }
  .footer__legal { text-align: center; }
}

/* ============================ Breakpoints ============================== */

@media (min-width: 48rem) {
  /* Two listings side by side. The calc accounts for the gap so a page scroll
     lands exactly on the next pair. */
  .carousel__track { grid-auto-columns: calc((100% - clamp(1rem, 2.5vw, 2rem)) / 2); }
}

@media (min-width: 48rem) {
  .form { grid-template-columns: 1fr 1fr; gap: 1.75rem; }
}

@media (min-width: 62rem) {
  .discover__grid { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); }
  .discover__portrait { position: sticky; top: 4rem; }
}

/* On a phone the portrait was taking well over half the screen, pushing the
   bio and the contact details below the fold. Shrinking it to 40% of the
   column — 60% smaller — brings the words up without losing the face. */
@media (max-width: 47.99rem) {
  .discover__portrait img { width: 40%; }
}
/* On a tablet the text runs under the photo too: at full width the portrait
   alone was taller than the screen. */
@media (min-width: 48rem) and (max-width: 61.99rem) {
  .discover__portrait img { width: 45%; }
}

/* ========================== Reduced motion ============================= */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  /* stage.js also collapses the runway to one viewport and holds a single
     frame, so the page reads as an ordinary site. */
  .stage__cue { display: none; }
}

/* Without JS the carousel is still a scroller and the stage still shows its
   gradient, but the frame sequence never starts — so hide the load indicator
   rather than leave it stuck at zero. */
.no-js .stage__rule { display: none; }

/* ================================ FAQ ================================== */

.faq__list {
  max-width: 52rem;
  border-top: 1px solid var(--border);
}
/* On wide screens the homepage questions sit beside their heading, in the
   same proportions as the Discover section, instead of leaving the right
   half of the screen empty. */
@media (min-width: 62rem) {
  .faq .wrap {
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    gap: clamp(2rem, 5vw, 4.5rem);
    align-items: start;
  }
  .faq .faq__list { max-width: none; }
}
.faq__aside { margin: -0.75rem 0 2rem; max-width: 28ch; color: var(--ivory-dim); }
.faq__aside a { color: var(--brass-lt); text-underline-offset: 0.2em; }
@media (min-width: 62rem) {
  .faq__aside { margin-bottom: 0; }
}
.faq__item { border-bottom: 1px solid var(--border); }

.faq__q {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1.5rem;
  padding: 1.35rem 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 36;
  font-size: clamp(1.1rem, 1.8vw, 1.3rem);
  line-height: 1.35;
}
.faq__q::-webkit-details-marker { display: none; }
/* A plus that turns into a minus: two hairlines, the vertical one folds away. */
.faq__q::after {
  content: '';
  flex: none;
  width: 1rem;
  height: 1rem;
  background:
    linear-gradient(var(--brass-lt), var(--brass-lt)) center / 100% 1.5px no-repeat,
    linear-gradient(var(--brass-lt), var(--brass-lt)) center / 1.5px 100% no-repeat;
  transition: background-size 0.25s var(--ease);
}
.faq__item[open] > .faq__q::after {
  background-size: 100% 1.5px, 1.5px 0;
}
.faq__q:hover { color: var(--brass-lt); }

.faq__a { padding: 0 0 1.5rem; max-width: 62ch; color: var(--ivory-dim); }
.faq__a p { margin: 0; }
.faq__a strong { color: var(--ivory); font-weight: 600; }

/* ======================== Floating call to action ====================== */

.cta {
  position: fixed;
  z-index: 40;
  right: max(1rem, env(safe-area-inset-right));
  bottom: max(1rem, env(safe-area-inset-bottom));
  display: flex;
  gap: 0.5rem;
  opacity: 0;
  transform: translateY(0.75rem);
  pointer-events: none;
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}
.cta[hidden] { display: none; }
.cta.is-shown { opacity: 1; transform: none; pointer-events: auto; }

.cta__main,
.cta__call {
  display: grid;
  place-items: center;
  min-height: 3rem;
  background: var(--brass);
  color: var(--slate);
  text-decoration: none;
  box-shadow: 0 0.5rem 1.75rem rgba(0, 0, 0, 0.45);
  transition: background-color 0.2s var(--ease);
}
.cta__main {
  padding: 0 1.5rem;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.cta__call { width: 3rem; border-radius: 50%; }
.cta__call svg { width: 1.3rem; height: 1.3rem; }
.cta__main { border-radius: 1.5rem; }
.cta__main:hover, .cta__call:hover,
.cta__main:focus-visible, .cta__call:focus-visible { background: var(--brass-lt); }

/* The call button is for phones; on a desktop the tel: link has nowhere to go. */
@media (hover: hover) and (pointer: fine) {
  .cta__call { display: none; }
}

/* ============================= Footer links ============================ */

.footer__links { display: flex; gap: 1.25rem; justify-content: flex-end; flex-wrap: wrap; }
.footer__links a { color: var(--ivory-dim); text-underline-offset: 0.2em; }
.footer__links a:hover { color: var(--brass-lt); }
@media (max-width: 40rem) {
  .footer__links { justify-content: center; }
}

/* ======================= Secondary pages (legal, 404) ================== */

.page-header {
  border-bottom: 1px solid var(--border);
  padding-block: 1.25rem;
}
.page-header .wrap {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.page-header__name {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 48;
  font-size: 1.35rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ivory);
  text-decoration: none;
}
.page-header__back { font-size: 0.82rem; letter-spacing: 0.1em; text-transform: uppercase; }

.doc { padding-block: clamp(3rem, 8vw, 6rem); }
.doc .section__title { margin-bottom: 1rem; }
.doc__meta { color: var(--ivory-dim); margin: 0 0 clamp(2rem, 5vw, 3rem); }
.doc__body { max-width: 68ch; color: var(--ivory-dim); }
.doc__body h2 {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 36;
  font-weight: 400;
  font-size: clamp(1.25rem, 2.2vw, 1.55rem);
  color: var(--ivory);
  margin: 2.5rem 0 0.75rem;
}
.doc__body p, .doc__body ul { margin: 0 0 1rem; }
.doc__body li { margin-bottom: 0.4rem; }
.doc__body strong { color: var(--ivory); font-weight: 600; }

.notfound { min-height: 70vh; display: grid; align-content: center; }
.notfound p { color: var(--ivory-dim); max-width: 46ch; margin: 0 0 2rem; }
.notfound__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }

/* ================================ Guides =============================== */

.page-header__nav { display: flex; gap: 1.5rem; flex-wrap: wrap; }

.guides__intro { max-width: 62ch; color: var(--ivory-dim); margin: -0.75rem 0 2rem; }
.guide .guides__intro { margin: 0 0 1rem; }
.guides__more { margin: 2rem 0 0; }
.guides__group {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 36;
  font-weight: 400;
  font-size: clamp(1.3rem, 2.4vw, 1.7rem);
  margin: 3rem 0 1.25rem;
}

.guide-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
  gap: 1rem;
}
.guide-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1.5rem;
  background: var(--slate-2);
  border: 1px solid var(--border);
  text-decoration: none;
  color: var(--ivory);
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.guide-card:hover,
.guide-card:focus-visible { border-color: var(--border-lit); background: var(--slate-3); }
.guide-card__kicker {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass-lt);
}
.guide-card__title {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 36;
  font-size: 1.2rem;
  line-height: 1.3;
}
.guide-card__text { font-size: 0.92rem; color: var(--ivory-dim); }

/* Homepage guide cards: the question people ask, one line on what the
   guide covers, and where the link goes. */
.guide-q {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 1.35rem 1.4rem;
  background: var(--slate-2);
  border: 1px solid var(--border);
  text-decoration: none;
  color: var(--ivory);
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.guide-q:hover,
.guide-q:focus-visible { border-color: var(--border-lit); background: var(--slate-3); }
.guide-q__q {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 36;
  font-size: 1.28rem;
  line-height: 1.3;
}
.guide-q__a { font-size: 0.95rem; line-height: 1.5; color: var(--ivory-dim); }
.guide-q__more {
  margin-top: auto;
  padding-top: 0.5rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brass-lt);
}

/* A guide page reads as a document: the body column is narrow for reading,
   the cards and boxes inside it use the full column. */
.guide .doc__body { max-width: 46rem; }
.guide .doc__body h3 {
  font-size: 1.05rem;
  color: var(--ivory);
  margin: 1.75rem 0 0.5rem;
}
.guide .doc__body ol { margin: 0 0 1rem; padding-left: 1.4rem; }
.guide .doc__body a { text-underline-offset: 0.2em; }

.crumbs {
  font-size: 0.82rem;
  color: var(--ivory-dim);
  margin: 0 0 1.5rem;
}
.crumbs a { color: var(--ivory-dim); }
.crumbs a:hover { color: var(--brass-lt); }

/* The direct answer, first on the page: what AI answers quote. */
.guide__answer {
  padding: 1.25rem 1.5rem;
  border-left: 2px solid var(--brass);
  background: var(--slate-2);
  color: var(--ivory);
  font-size: 1.05rem;
}

.guide-quote {
  margin: 0 0 1.25rem;
  padding: 1.25rem 1.5rem;
  border: 1px solid var(--border);
}
.guide-quote blockquote {
  margin: 0 0 0.75rem;
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 30;
  color: var(--ivory);
  line-height: 1.5;
}
.guide-quote blockquote::before { content: '\201C'; }
.guide-quote blockquote::after { content: '\201D'; }
.guide-quote figcaption {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass-lt);
}
.guide-quote__note {
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ivory-dim);
}

.guide .faq__list { margin-bottom: 1rem; }

.guide-cta {
  margin: 2.5rem 0;
  padding: 1.75rem;
  background: var(--slate-2);
  border: 1px solid var(--border-lit);
}
.guide-cta__title {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 36;
  font-size: 1.35rem;
  color: var(--ivory);
}
.guide-cta .button { margin-top: 0.5rem; }

.guide-author {
  display: flex;
  gap: 1.25rem;
  align-items: flex-start;
  margin-top: 3rem;
  padding-top: 2rem;
  border-top: 1px solid var(--border);
  font-size: 0.92rem;
}
.guide-author__photo {
  width: 96px;
  height: 120px;
  object-fit: cover;
  flex: none;
  border: 1px solid var(--border);
}
.guide-author__name { color: var(--ivory); font-weight: 600; margin-bottom: 0.35rem !important; }
.guide-author p { margin: 0 0 0.6rem; }
@media (max-width: 30rem) {
  .guide-author { flex-direction: column; }
}

/* County maps (tools/maps.mjs): inline SVG, so they take the page's colors.
   Sizes are in map units; the map is 800 units wide and never drawn narrower
   than 600px, so names stay readable. On a phone it scrolls sideways in its
   own box (page.js starts it at the highlighted town). */
.cmap { margin: 1.5rem 0 2rem; }
.cmap__scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  border: 1px solid var(--border);
  background: var(--slate);
}
.cmap__svg { display: block; width: 100%; min-width: 600px; height: auto; }
.cmap__scroll:focus-visible,
.table-wrap:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.cmap__area {
  fill: var(--slate-3);
  stroke: rgba(242, 238, 231, 0.32);
  stroke-width: 1;
  stroke-linejoin: round;
}
.cmap__area.is-hl { fill: var(--brass); }
.cmap__area.str-green { fill: #63a777; }
.cmap__area.str-yellow { fill: #d8b64e; }
.cmap__area.str-red { fill: #cf6a5f; }
/* Colors that only tell neighboring municipalities apart (no meaning). */
.cmap__area.cat-0 { fill: #8fa9c0; }
.cmap__area.cat-1 { fill: #7fb3ab; }
.cmap__area.cat-2 { fill: #cdb98f; }
.cmap__area.cat-3 { fill: #ab9dbf; }
.cmap__area.cat-4 { fill: #a9b67f; }
.cmap__area.cat-5 { fill: #c99c86; }
.cmap__label {
  font-family: var(--font-body);
  font-size: 16px;
  fill: var(--ivory-dim);
  text-anchor: middle;
}
.cmap__label--sm { font-size: 13.5px; }
.cmap__label.is-hl,
.cmap__svg--str .cmap__label,
.cmap__svg--cat .cmap__label { fill: var(--slate); font-weight: 600; }
.cmap__svg--cat .cmap__area { stroke: var(--slate); stroke-width: 1.2; }
.cmap__num circle { fill: var(--slate); stroke: var(--ivory-dim); stroke-width: 1.2; }
.cmap__num text {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  fill: var(--ivory);
  text-anchor: middle;
}
.cmap__leader { stroke: var(--ivory-dim); stroke-width: 1.2; }
.cmap__pin { fill: var(--ivory-dim); }
.cmap__mark circle { fill: var(--ivory); stroke: var(--slate); stroke-width: 2.5; }
.cmap__mlabel {
  font-family: var(--font-body);
  font-size: 19px;
  font-weight: 600;
  fill: var(--ivory);
  stroke: var(--slate);
  stroke-width: 5px;
  stroke-linejoin: round;
  paint-order: stroke;
}
.cmap figcaption { font-size: 0.88rem; color: var(--ivory-dim); margin-top: 0.75rem; }
.cmap__hint { display: none; }
@media (max-width: 40rem) { .cmap__hint { display: inline; } }
.cmap__list { font-size: 0.92rem; margin: 0 0 1.5rem; }
.cmap__list p { margin: 0 0 0.5rem; }

/* Short-term rental colors, shared by the map, its legend and the table. */
.str-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.25rem;
  list-style: none;
  padding: 0;
  margin: 0 0 0.6rem;
  color: var(--ivory);
}
.str-legend li { margin: 0; }
.str-swatch {
  display: inline-block;
  width: 0.8em;
  height: 0.8em;
  margin-right: 0.45em;
  vertical-align: -0.05em;
  border-radius: 2px;
}
.str-swatch--green { background: #63a777; }
.str-swatch--yellow { background: #d8b64e; }
.str-swatch--red { background: #cf6a5f; }

/* Tables: scroll sideways on a phone instead of squeezing the columns. */
.table-wrap { overflow-x: auto; margin: 0 0 1.5rem; border: 1px solid var(--border); }
.table-wrap table { width: 100%; border-collapse: collapse; font-size: 0.92rem; min-width: 34rem; }
.table-wrap caption {
  caption-side: top;
  text-align: left;
  padding: 0.75rem 1rem;
  color: var(--ivory);
  font-weight: 600;
}
.table-wrap th,
.table-wrap td {
  text-align: left;
  vertical-align: top;
  padding: 0.7rem 1rem;
  border-top: 1px solid var(--border);
}
.table-wrap thead th {
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brass-lt);
  font-weight: 600;
  background: var(--slate-2);
}
.table-wrap tbody th { color: var(--ivory); font-weight: 600; }
.str-table td:nth-child(2) { white-space: nowrap; }

/* Market numbers. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  gap: 1rem;
  margin: 0 0 0.75rem;
}
.doc__body .stat {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin: 0;
  padding: 1.25rem;
  background: var(--slate-2);
  border: 1px solid var(--border);
}
.stat__value {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 36;
  font-size: 1.6rem;
  color: var(--ivory);
}
.stat__label { font-size: 0.85rem; }
.stats__note { font-size: 0.85rem; }

/* Photos. */
.guide-photo { margin: 0 0 1.75rem; }
.guide-photo img { width: 100%; height: auto; border: 1px solid var(--border); }
.guide-photo figcaption { font-size: 0.85rem; margin-top: 0.6rem; }
.guide-photo__credit { opacity: 0.75; }
.guide-photos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: 1rem;
  margin: 0 0 1.5rem;
}
.guide-photos .guide-photo { margin: 0; }

/* Ryth's take: his own words, set apart from the rest of the guide. */
.guide-take {
  margin: 0 0 1.5rem;
  padding: 1.5rem 1.75rem;
  background: var(--slate-2);
  border-left: 2px solid var(--brass);
}
.guide-take blockquote { margin: 0 0 0.75rem; }
.guide-take blockquote p {
  margin: 0;
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 30;
  font-size: 1.1rem;
  line-height: 1.55;
  color: var(--ivory);
}
.guide-take figcaption {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass-lt);
}
