/* ============================================================
   Paseo Retreat - shared stylesheet
   Brand (Aug 2026): terracotta #B85B3D · bone #FAF6F0 ·
   cream #FDF9F4 · sand #E4D9C8 · ink #3A332C · muted #A9A093 ·
   moss #3D5A40
   Terracotta matches the logo PNG exactly. Andrew chose it over the
   older #B5623F brand token on 2026-08-08. Do not reintroduce #B5623F.

   Fonts (Option 5, "Warm", chosen 2026-08-08): EB Garamond
   (display) · Karla (body and small caps labels). Andrew reviewed
   five pairings side by side and picked this one. Marcellus was
   tried first and rejected as too stiff to read at length.
   Reading comfort was left at the tighter setting on purpose.
   ============================================================ */

:root {
  --terracotta: #B85B3D;
  --terracotta-deep: #9C4D34;
  --bone: #FAF6F0;
  --cream: #FDF9F4;
  --sand: #E4D9C8;
  --sand-light: #F2EBDF;
  --ink: #3A332C;
  --ink-soft: #6E6558;
  --muted: #A9A093;
  --moss: #3D5A40;
  --moss-deep: #2F4632;

  /* ---------- ACCENTS, added 2026-08-10 ----------
     Andrew: "Santa Fe is about vibrancy. Look at all the colors and patterns
     that I utilize in the casita, and that's what I want. I want some colors
     to pop and get that emotional feel."

     These are not invented. Every one was sampled out of the casita's own
     photographs, so they cannot clash with the pictures they sit beside:

       turquoise  the Adirondack chairs on the deck and the Navajo rug
       indigo     the bed linens and the framed landscape over the hearth
       gold       the vigas and the plaster in late afternoon light

     Measured across four photographs, the frames are 24% red/terracotta,
     19% amber/gold, 18% indigo and 5% turquoise. Terracotta stays the primary
     because it is already the brand and it is genuinely the dominant colour
     of the place. These three are supporting accents, used on small elements
     so the palette gains range without becoming a different brand.

     All three are darkened from the raw sampled values to clear 4.5:1 against
     --bone, so they are safe for text and not only for decoration. Do not
     lighten them without re-checking contrast. */
  --turquoise: #0A6A82;
  --indigo: #3A5F8A;
  --gold: #855C11;
  --font-display: "EB Garamond", Georgia, "Times New Roman", serif;
  --font-body: "Karla", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-accent: "Karla", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --max: 1120px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
}

/* ---------- skip link ---------- */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--bone);
  padding: 0.6rem 1rem;
  z-index: 100;
}
.skip-link:focus { left: 0; }

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.7;
  color: var(--ink);
  background: var(--bone);
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: var(--moss); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--terracotta); }
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--moss);
  outline-offset: 2px;
}

/* ---------- type ---------- */
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 400; /* EB Garamond goes heavier, but headings stay at 400 */
  line-height: 1.15;
  letter-spacing: 0.005em;
  margin: 0 0 0.6em;
}
h1 { font-size: clamp(2.5rem, 6vw, 4.5rem); }
h2 { font-size: clamp(1.85rem, 3.6vw, 2.75rem); }
h3 { font-size: clamp(1.3rem, 2.2vw, 1.65rem); }
p { margin: 0 0 1.1em; }
.lede { font-size: clamp(1.05rem, 1.6vw, 1.25rem); color: var(--ink-soft); max-width: 46em; }
.eyebrow {
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--terracotta);
  display: block;
  margin: 0 0 1.1rem;
}
.eyebrow--quiet { color: var(--ink-soft); }

/* ---------- layout ---------- */
.container { max-width: var(--max); margin: 0 auto; padding-left: var(--gutter); padding-right: var(--gutter); }
.section { padding: clamp(3.5rem, 8vw, 6.5rem) 0; }
.section--alt { background: var(--cream); border-top: 1px solid var(--sand); border-bottom: 1px solid var(--sand); }
.section--tight { padding: clamp(2.25rem, 5vw, 3.5rem) 0; }
.rule { border: none; border-top: 1px solid var(--sand); margin: 0; }
.measure { max-width: 42em; }
.center { text-align: center; }
.center .lede, .center .measure { margin-left: auto; margin-right: auto; }

/* ---------- buttons ---------- */
.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 0.85rem 1.7rem;
  background: var(--terracotta);
  color: var(--bone);
  border: 1px solid var(--terracotta);
  border-radius: 2px;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.btn:hover { background: var(--terracotta-deep); border-color: var(--terracotta-deep); color: var(--bone); }
.btn--ghost { background: transparent; color: var(--terracotta); }
.btn--ghost:hover { background: var(--terracotta); color: var(--bone); }
.btn--moss { background: var(--moss); border-color: var(--moss); }
.btn--moss:hover { background: var(--moss-deep); border-color: var(--moss-deep); }
.textlink {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--moss);
}

/* ---------- header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(250, 246, 240, 0.96);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--sand);
}
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  min-height: 4.25rem;
}
/* Wordmark lockup: stepped adobe mark plus type, rebuilt from the Canva logo
   as inline SVG so it inherits currentColor. Terracotta in the header, sand
   in the footer, with no second image file and no baked-in background. */
.wordmark {
  display: inline-flex;
  align-items: center;
  /* The wordmark is the link home, and it was 31px tall on a phone. */
  min-height: 2.75rem;
  gap: 0.55em;
  font-family: var(--font-display);
  font-size: 1.15rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--terracotta);
  text-decoration: none;
  white-space: nowrap;
}
.wordmark:hover { color: var(--terracotta); }
.wordmark-mark {
  width: 1.75em;
  height: auto;
  flex: none;
  overflow: visible;
}
.site-nav { display: flex; align-items: center; gap: clamp(1rem, 2.2vw, 1.9rem); }
.site-nav a {
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  padding: 0.25rem 0;
  border-bottom: 1px solid transparent;
}
.site-nav a:hover { color: var(--terracotta); }
.site-nav a[aria-current="page"] { border-bottom-color: var(--terracotta); color: var(--terracotta); }
/* Book Direct in the header. The padding alone left it at 31px on mobile,
   under the 44px touch minimum, on the single most important button here. */
.site-nav .btn {
  font-size: 0.82rem;
  padding: 0.6rem 1.2rem;
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
}
.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--sand);
  border-radius: 2px;
  padding: 0.5rem 0.7rem;
  /* 44px minimum touch target. Was rendering at 32px on a phone, and this is
     the one control every mobile visitor has to hit to navigate at all. */
  min-height: 2.75rem;
  min-width: 2.75rem;
  cursor: pointer;
  color: var(--ink);
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* ---------- hero ---------- */
.hero { position: relative; }
.hero .ph--hero {
  min-height: clamp(20rem, 55vh, 34rem);
  border-left: none;
  border-right: none;
  border-top: none;
}
/* Top padding only. The left and right padding MUST stay as var(--gutter),
   because .hero-copy also carries .container and the shorthand would otherwise
   overwrite the container gutter with 0. That is invisible on desktop, where the
   container is centred inside wide margins, but on a phone the container fills
   the screen and the headline ends up touching both edges. */
.hero-copy {
  padding: clamp(2.5rem, 6vw, 4.5rem) var(--gutter) 0;
}
.hero-copy h1 { max-width: 15em; }
.hero-cta { display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap; margin-top: 2rem; }

/* ---------- image placeholders ---------- */
.ph {
  background: var(--sand-light);
  border: 1px solid var(--sand);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 1rem;
  min-height: 14rem;
}
.ph span {
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  line-height: 1.7;
  color: var(--ink-soft);
  max-width: 26em;
}
.ph--wide { min-height: 18rem; }
.ph--tall { min-height: 22rem; }
.ph--sm { min-height: 10rem; }

/* ---------- real photography ---------- */
/* Placeholders (.ph) stay wherever a photo has not landed yet, so the page
   keeps documenting what is still missing. Slots whose file exists use these
   rules instead. Deliberately almost no cropping here: the crops that mattered
   (3:1 hero bands, 2:3 portraits) are already baked into the JPEGs, so CSS
   should not re-cut them. Only the hero gets a fixed band height, because it
   has to fill a full-bleed strip at any viewport width. */
img.photo {
  width: 100%;
  height: auto;
  display: block;
  background: var(--sand-light);
}
.hero img.photo--hero {
  height: clamp(20rem, 55vh, 34rem);
  object-fit: cover;
}
/* Card thumbnails hold a 3:2 box so a row of cards lines up even when some
   slots are still placeholders. The source files are already 3:2, so no crop
   results. */
img.photo--card { aspect-ratio: 3 / 2; object-fit: cover; }
/* Gallery grids mix landscape and portrait crops. align-self:start lets each
   image keep its own shape instead of being stretched to the row height. */
.gallery img.photo { align-self: start; }

/* ============================================================
   HERO SLIDER (added 2026-08-10)
   Andrew: "I don't like just one photo, I want it to be
   interactive and moving and showcase all the beautiful
   components."

   It does auto-advance, which the unit galleries deliberately do
   not. The difference is that nothing is being read here: a hero
   image carries no text the visitor is part-way through. Three
   guards keep it from becoming the kind of carousel the April
   design doc warned about:
     1. it stops on hover and on keyboard focus
     2. prefers-reduced-motion stops it dead, no fade, no timer
     3. arrows and dots are always there, so it is never the only
        way to see a photo
   Only the first slide loads eagerly, so the largest contentful
   paint is one image, exactly as before. The rest are lazy.
   With JavaScript off, slide one shows and nothing is broken.
   ============================================================ */
.hero-slider { position: relative; }
.hs-frame {
  position: relative;
  height: clamp(20rem, 55vh, 34rem);
  overflow: hidden;
  background: var(--sand-light);
}
.hs-frame img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 900ms ease-in-out;
}
.hs-frame img.is-active { opacity: 1; }

.hs-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  border: 1px solid var(--sand);
  background: rgba(250, 246, 240, 0.9);
  color: var(--ink);
  font-size: 1.5rem;
  line-height: 1;
  padding: 0 0 0.15rem;
  cursor: pointer;
  display: none;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 6px rgba(58, 51, 44, 0.18);
}
.hero-slider[data-ready] .hs-arrow { display: flex; }
.hs-arrow:hover { background: var(--bone); }
.hs-arrow:focus-visible { outline: 2px solid var(--terracotta); outline-offset: 2px; }
.hs-arrow--prev { left: var(--gutter); }
.hs-arrow--next { right: var(--gutter); }

.hs-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.5rem;
  display: flex;
  justify-content: center;
  gap: 0;
}
.hs-dot {
  width: 2.25rem;
  height: 2.75rem;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  position: relative;
}
.hs-dot::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  border: 1px solid rgba(250, 246, 240, 0.9);
  background: rgba(58, 51, 44, 0.25);
}
.hs-dot[aria-current="true"]::before {
  background: var(--bone);
  border-color: var(--bone);
}
.hs-dot:focus-visible { outline: 2px solid var(--terracotta); outline-offset: -4px; }

@media (prefers-reduced-motion: reduce) {
  .hs-frame img { transition: none; }
}

/* ---------- property tour video ---------- */
/* Click to play, never autoplay. preload="none" plus a poster means the file
   costs nothing until someone presses play. The footage is portrait 1080x1920
   and handheld, so it sits in a phone-shaped frame and is never full-bleed. */
.video-figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
}
.video-frame {
  width: 100%;
  max-width: 19rem;
  aspect-ratio: 9 / 16;
  background: var(--ink);
  border: 1px solid var(--sand);
  border-radius: 16px;
  overflow: hidden;
}
.video-frame video {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  background: var(--ink);
}
.video-caption {
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0;
}

/* ---------- cards ---------- */
.card-grid { display: grid; gap: 1.5rem; grid-template-columns: repeat(3, 1fr); }
.card-grid--2 { grid-template-columns: repeat(2, 1fr); }
.card-grid--4 { grid-template-columns: repeat(4, 1fr); }
.card {
  background: var(--cream);
  border: 1px solid var(--sand);
  border-radius: 2px;
  padding: 1.75rem;
  display: flex;
  flex-direction: column;
}
.card .eyebrow { margin-bottom: 0.75rem; }
.card h3 { margin-bottom: 0.5rem; }
.card p { font-size: 0.95rem; }
.card .card-cta { margin-top: auto; padding-top: 1rem; }
.card--flush { padding: 0; overflow: hidden; }
.card--flush .card-body { padding: 1.75rem; display: flex; flex-direction: column; flex: 1; }

/* unit cards */
.unit-specs {
  font-family: var(--font-accent);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 0.9rem;
}
.unit-price { font-family: var(--font-display); font-size: 1.6rem; color: var(--ink); }
.badge {
  display: inline-block;
  font-family: var(--font-accent);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--moss);
  border: 1px solid var(--moss);
  border-radius: 2px;
  padding: 0.15rem 0.55rem;
  margin-left: 0.5rem;
  vertical-align: middle;
}

/* ---------- amenity list ---------- */
.amenity-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem 2rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.amenity-grid li { border-top: 1px solid var(--sand); padding-top: 0.9rem; }
.amenity-grid strong { display: block; font-weight: 700; font-size: 0.95rem; margin-bottom: 0.15rem; }
.amenity-grid span { font-size: 0.88rem; color: var(--ink-soft); }

/* ---------- gallery ---------- */
.gallery { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; }
.gallery .ph { min-height: 11rem; }

/* ---------- tables ---------- */
.table-wrap { overflow-x: auto; }
table.distances { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
table.distances th {
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--ink-soft);
  text-align: left;
  padding: 0.6rem 1rem 0.6rem 0;
  border-bottom: 1px solid var(--ink);
}
table.distances td { padding: 0.75rem 1rem 0.75rem 0; border-bottom: 1px solid var(--sand); }

/* ---------- reviews ---------- */
.trust-strip {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 2.2rem);
  text-align: center;
}
.trust-strip .star { color: var(--terracotta); }
.quote-card { background: var(--cream); border: 1px solid var(--sand); border-radius: 2px; padding: 1.75rem; }
.quote-card blockquote { margin: 0 0 1rem; font-family: var(--font-display); font-size: 1.2rem; line-height: 1.45; }
.quote-card cite {
  font-style: normal;
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
/* Verbatim guest quotes set beside the claim they confirm, rather than only in
   the reviews block. Never edited, never stitched: one contiguous sentence as
   the guest wrote it, or nothing. */
.pull-quote {
  margin: 2rem 0 0;
  padding: 0 0 0 1.25rem;
  border-left: 2px solid var(--terracotta);
  max-width: 40rem;
}
.pull-quote p {
  margin: 0 0 0.6rem;
  font-family: var(--font-display);
  font-size: 1.2rem;
  line-height: 1.45;
}
.pull-quote cite {
  font-style: normal;
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.center .pull-quote { margin-left: auto; margin-right: auto; text-align: left; }
/* The whole quote is clickable through to the full reviews. Done with a
   "stretched link": one real anchor for screen readers and keyboards, whose
   ::after is expanded to cover the block for mouse users. Avoids a div with a
   click handler, which is unreachable by keyboard. */
.pull-quote { position: relative; transition: border-color 0.15s ease; }
.pull-quote-more {
  display: inline-block;
  margin-left: 0.75rem;
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--terracotta);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.pull-quote-more::after { content: ""; position: absolute; inset: 0; }
.pull-quote:hover { border-left-color: var(--ink); }
.pull-quote:hover .pull-quote-more { border-bottom-color: var(--terracotta); }
.pull-quote-more:focus-visible { outline: 2px solid var(--terracotta); outline-offset: 3px; }

/* ============================================================
   Paseo Retreat: reviews section (was partials/reviews-section.css)
   New rules only. Everything else on that section is carried by
   existing conventions: .section, .section--alt, .container,
   .eyebrow, .lede, .card-grid, .card-grid--2, .quote-card, .center.
   ============================================================ */

/* ---------- rating line ---------- */
/* The score is real text, so a screen reader announces
   "4.96 out of 5, across 26 reviews on Airbnb". The stars are
   inline SVG drawn in currentColor, hidden from assistive tech,
   and carry no meaning on their own. No icon font, no image file,
   no network request. If SVG fails to paint, the text still reads. */
.review-rating {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 0.4rem 0.9rem;
  margin: 0 0 1.4rem;
}
.review-stars {
  width: 7.5rem;
  height: auto;
  flex: none;
  color: var(--terracotta);
  fill: currentColor;
  align-self: center;
}
.review-score {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 2.2rem);
  line-height: 1;
  color: var(--ink);
}
.review-score strong { font-weight: 400; }
.review-count {
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.review-intro { margin-bottom: 0; }
.review-head { margin-bottom: clamp(2rem, 4vw, 2.75rem); }

/* ---------- review cards ---------- */
.review-grid { align-items: stretch; }
.quote-card--review {
  display: flex;
  flex-direction: column;
}
/* Verbatim guest text runs longer than a pull quote, so it sits a
   step below the .quote-card display size for comfortable reading. */
.quote-card--review blockquote {
  font-size: clamp(1.05rem, 1.5vw, 1.18rem);
  line-height: 1.5;
  margin-bottom: 1.25rem;
}
.quote-card--review cite {
  margin-top: auto;
  display: block;
  color: var(--ink);
}
.review-when {
  color: var(--ink-soft);
}
.review-when::before {
  content: "\00B7";
  margin: 0 0.4rem;
  color: var(--muted);
}

/* ---------- source and booking note ---------- */
.review-source {
  margin: clamp(2rem, 4vw, 2.75rem) auto 0;
  max-width: 46em;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

@media (max-width: 600px) {
  .review-rating { gap: 0.35rem 0.6rem; }
  .review-stars { width: 6rem; }
}

/* ---------- steps ---------- */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; counter-reset: step; list-style: none; margin: 0; padding: 0; }
.steps li { border-top: 1px solid var(--sand); padding-top: 1rem; counter-increment: step; }
.steps li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  color: var(--terracotta);
  display: block;
  margin-bottom: 0.5rem;
}
.steps strong { display: block; margin-bottom: 0.2rem; }
.steps span { font-size: 0.92rem; color: var(--ink-soft); }

/* ---------- booking panel ---------- */
.book-panel {
  background: var(--cream);
  border: 1px solid var(--sand);
  border-radius: 2px;
  padding: clamp(2rem, 5vw, 3.5rem);
  text-align: center;
}
.book-panel .eyebrow { color: var(--moss); }
.book-fallback { display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap; margin-top: 1.75rem; }
.trust-signals { list-style: none; margin: 2rem 0 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 0.75rem 2rem; }
.trust-signals li { font-family: var(--font-accent); font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-soft); }

/* ---------- FAQ (accordion via details/summary) ---------- */
.faq-group { border-top: 1px solid var(--sand); }
.faq-group details { border-bottom: 1px solid var(--sand); }
.faq-group summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1.5rem;
  padding: 1.2rem 0;
  font-weight: 600;
  font-size: 1.02rem;
}
.faq-group summary::-webkit-details-marker { display: none; }
.faq-group summary::after {
  content: "+";
  font-family: var(--font-accent);
  font-size: 1.1rem;
  color: var(--terracotta);
  flex-shrink: 0;
}
.faq-group details[open] summary::after { content: "\2212"; }
.faq-group .faq-a { padding: 0 0 1.4rem; max-width: 44em; color: var(--ink-soft); }
.faq-group .faq-a p:last-child { margin-bottom: 0; }

/* ---------- guide (santa-fe) ---------- */
.guide-list { list-style: none; margin: 0; padding: 0; }
.guide-list li { border-top: 1px solid var(--sand); padding: 1.5rem 0; display: grid; grid-template-columns: minmax(0, 1fr) 12rem; gap: 0.5rem 2rem; }
.guide-list h3 { margin-bottom: 0.35rem; }
.guide-list p { margin: 0; font-size: 0.95rem; color: var(--ink-soft); max-width: 40em; }
.guide-list .dist {
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--moss);
  text-align: right;
  padding-top: 0.55rem;
}

/* ---------- guide directions links + map slot (2026-08-10) ----------
   Every place on the Santa Fe guide carries a link that opens Google Maps
   with a route from the front gate to that place. Hard rule: the distance
   printed next to it was routed the same way, never estimated. See DRAFT_24.
   min-height keeps it a real touch target on a phone. */
.guide-list .dirlink {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  margin-top: 0.15rem;
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--terracotta);
  border-bottom: 1px solid transparent;
}
.guide-list .dirlink:hover { border-bottom-color: var(--terracotta); }
.guide-list .dist { display: flex; flex-direction: column; align-items: flex-end; }

/* Holds the Google My Maps iframe once Andrew builds it. Boxed so the
   placeholder reads as deliberate rather than broken. */
.map-slot {
  border: 1px dashed var(--sand);
  border-radius: 2px;
  background: var(--cream);
  padding: 1.5rem;
  margin: 2rem 0 0.5rem;
}
.map-slot p { margin: 0; font-size: 0.95rem; color: var(--ink-soft); }
.map-slot iframe { display: block; width: 100%; height: 480px; border: 0; }
/* Applied once the real map is in. The dashed frame and padding existed only so
   an empty slot read as deliberate rather than broken, and they box the live
   map in for no reason. */
.map-slot--live { border: 0; padding: 0; border-radius: 3px; overflow: hidden; }

@media (max-width: 600px) {
  .guide-list .dist { align-items: flex-start; }
  .map-slot iframe { height: 360px; }
}

/* ---------- forms ---------- */
.form { max-width: 36rem; }
.form label {
  display: block;
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 1.25rem 0 0.4rem;
}
.form input, .form select, .form textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--ink);
  background: #FFFFFF;
  border: 1px solid var(--sand);
  border-radius: 2px;
  padding: 0.75rem 0.9rem;
}
.form textarea { min-height: 9rem; resize: vertical; }
.form .btn { margin-top: 1.75rem; }

/* ---------- story ---------- */
.story-body { max-width: 40em; font-size: 1.08rem; }
.story-body p { margin-bottom: 1.4em; }
.signoff { font-family: var(--font-display); font-size: 1.5rem; margin-top: 2rem; }

/* ---------- footer ---------- */
.site-footer {
  background: #2E2822;
  color: var(--sand);
  margin-top: clamp(3rem, 7vw, 5rem);
  padding: clamp(2.75rem, 6vw, 4rem) 0;
  font-size: 0.92rem;
}
.site-footer .wordmark { font-size: 1.6rem; }
.footer-grid { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2rem; align-items: flex-start; }
.footer-meta { font-family: var(--font-accent); font-size: 0.75rem; letter-spacing: 0.06em; line-height: 2.1; }
.site-footer a { color: var(--sand); }
.site-footer a:hover { color: var(--terracotta); }

/* Footer links were rendering 14px tall on a phone, stacked one per line.
   These are standalone navigation, not inline prose, so they get a real
   touch target. inline-flex keeps them on their own line as the <br>
   markup intends, while giving each one 44px of height to aim at. */
.footer-meta a,
.site-footer a[href^="mailto:"],
.site-footer a[href^="tel:"] {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
}
/* Footer social icons. Added 2026-08-11.

   fill: currentColor is the whole trick here. The icons inherit the footer's
   sand colour and the terracotta hover from the .site-footer a rules above,
   so there is no second colour to keep in sync and no hard-coded hex that
   would go stale if the footer palette ever moves.

   The link box is 44px and the glyph inside it is 20px. The rest is a touch
   target, the same 2.75rem the footer text links already got. The negative
   left margin pulls that padding back so the first icon lines up with the
   wordmark above it rather than sitting a dozen pixels to its right. */
.social {
  display: flex;
  gap: 0.25rem;
  margin-top: 0.5rem;
  margin-left: -0.75rem;
}
.social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
}
.social svg {
  width: 1.25rem;
  height: 1.25rem;
  fill: currentColor;
  display: block;
}
.social a:focus-visible {
  outline: 2px solid var(--sand);
  outline-offset: 2px;
}

.footer-bottom {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(228, 217, 200, 0.25);
  font-family: var(--font-accent);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  color: rgba(228, 217, 200, 0.7);
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  justify-content: space-between;
}

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .card-grid, .card-grid--4 { grid-template-columns: repeat(2, 1fr); }
  .amenity-grid { grid-template-columns: repeat(2, 1fr); }
  .gallery { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 768px) {
  .nav-toggle { display: block; }
  .site-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    background: var(--bone);
    border-bottom: 1px solid var(--sand);
    padding: 0.5rem var(--gutter) 1.25rem;
  }
  .site-nav.is-open { display: flex; }
  .site-nav a { padding: 0.75rem 0; width: 100%; border-bottom: none; font-size: 1rem; }
  .site-nav .btn { margin-top: 0.75rem; width: auto; }
}

@media (max-width: 600px) {
  .card-grid, .card-grid--2, .card-grid--4 { grid-template-columns: 1fr; }
  .amenity-grid { grid-template-columns: 1fr; }
  .gallery { grid-template-columns: 1fr; }
  .guide-list li { grid-template-columns: 1fr; }
  .guide-list .dist { text-align: left; padding-top: 0; order: -1; }
  .steps { grid-template-columns: 1fr; }
}

/* ============================================================
   UNIT GALLERY (added 2026-08-09)
   Andrew asked for "a slider or something like that so there can
   be multiple" photos per unit. The April design doc's Don'ts list
   forbids carousels; that instinct is about AUTO-ROTATING carousels,
   which move content out from under the reader and hurt
   accessibility. This is not one. There is no autoplay, no timer,
   and nothing is hidden from assistive tech: the track is a plain
   horizontally scrollable list, every image is in the DOM and
   reachable by scroll, swipe, keyboard, or the arrow buttons.
   With JavaScript off it degrades to a scroll-snap strip that
   still works. The buttons, counter and lightbox are added by JS.
   ============================================================ */
.gallery-slider { position: relative; }

.gs-track {
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: thin;
  scrollbar-color: var(--sand) transparent;
  -webkit-overflow-scrolling: touch;
}
.gs-track:focus-visible { outline: 2px solid var(--terracotta); outline-offset: 3px; }
.gs-track::-webkit-scrollbar { height: 6px; }
.gs-track::-webkit-scrollbar-thumb { background: var(--sand); border-radius: 3px; }

.gs-slide {
  flex: 0 0 100%;
  margin: 0;
  scroll-snap-align: center;
  position: relative;
}
.gs-slide img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background: var(--sand-light);
}
/* Only offer the zoom affordance once the lightbox actually exists. */
.js-gallery .gs-slide img { cursor: zoom-in; }

/* Caption sits on the image so the track stays a clean band of
   photos and the arrow buttons can centre on it honestly. */
.gs-cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 2.5rem 0.85rem 0.7rem;
  font-family: var(--font-accent);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #fff;
  background: linear-gradient(to top, rgba(24,20,16,0.72), rgba(24,20,16,0));
  pointer-events: none;
}

.gs-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  /* 2.75rem = 44px, Apple's minimum touch target. Was 2.6rem (41.6px). */
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  border: 1px solid var(--sand);
  background: rgba(250, 246, 240, 0.94);
  color: var(--ink);
  font-size: 1.5rem;
  line-height: 1;
  padding: 0 0 0.15rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 6px rgba(58, 51, 44, 0.18);
}
.gs-btn:hover { background: var(--bone); border-color: var(--muted); }
.gs-btn:focus-visible { outline: 2px solid var(--terracotta); outline-offset: 2px; }
.gs-btn[disabled] { opacity: 0.35; cursor: default; }
.gs-prev { left: 0.6rem; }
.gs-next { right: 0.6rem; }

.gs-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 0.6rem;
}
.gs-count {
  margin: 0;
  font-family: var(--font-accent);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  color: var(--ink-soft);
}
.gs-dots { display: flex; gap: 0; flex-wrap: wrap; }

/* The dot you SEE stays 8px. The thing you can HIT is 44px tall, drawn as
   transparent padding around it. Previously the button itself was 8px square,
   which is not a control on a touch screen, it is a coin toss. */
.gs-dot {
  width: 1.35rem;
  height: 2.75rem;
  padding: 0;
  border: none;
  background: none;
  position: relative;
  cursor: pointer;
}
.gs-dot::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  border: 1px solid var(--muted);
  background: transparent;
}
.gs-dot[aria-current="true"]::before { background: var(--terracotta); border-color: var(--terracotta); }
.gs-dot:focus-visible { outline: 2px solid var(--terracotta); outline-offset: 2px; }

/* ---------- lightbox ---------- */
.gs-lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(24, 20, 16, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(1rem, 4vw, 3rem);
}
.gs-lightbox[hidden] { display: none; }
.gs-lb-figure {
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
}
.gs-lb-figure img {
  max-width: 100%;
  max-height: 78vh;
  width: auto;
  object-fit: contain;
}
.gs-lb-figure figcaption {
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sand);
  text-align: center;
}
.gs-lb-close,
.gs-lb-nav {
  position: absolute;
  border: 1px solid rgba(228, 217, 200, 0.4);
  background: rgba(24, 20, 16, 0.5);
  color: var(--bone);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.gs-lb-close {
  top: 1rem;
  right: 1rem;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  font-size: 1.6rem;
  line-height: 1;
  padding: 0 0 0.2rem;
}
.gs-lb-nav {
  top: 50%;
  transform: translateY(-50%);
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  font-size: 1.8rem;
  line-height: 1;
  padding: 0 0 0.2rem;
}
.gs-lb-prev { left: 1rem; }
.gs-lb-next { right: 1rem; }
.gs-lb-close:hover,
.gs-lb-nav:hover { background: rgba(184, 91, 61, 0.85); border-color: var(--terracotta); }
.gs-lb-close:focus-visible,
.gs-lb-nav:focus-visible { outline: 2px solid var(--terracotta); outline-offset: 2px; }
body.gs-lb-open { overflow: hidden; }

/* Honour a reduced-motion preference: snap instantly, never glide. */
@media (prefers-reduced-motion: reduce) {
  .gs-track { scroll-behavior: auto; }
}

@media (max-width: 600px) {
  .gs-btn { width: 2.2rem; height: 2.2rem; font-size: 1.25rem; }
  .gs-lb-nav { width: 2.5rem; height: 2.5rem; font-size: 1.5rem; }
  .gs-lb-prev { left: 0.4rem; }
  .gs-lb-next { right: 0.4rem; }
}

/* Full-width variant, used for the casita gallery on the stay page where
   the slider gets the whole content column rather than half a card. */
.gallery-slider--wide .gs-cap {
  font-size: 0.74rem;
  padding: 3rem 1.25rem 1rem;
}
.gallery-slider--wide .gs-btn { width: 3rem; height: 3rem; font-size: 1.7rem; }
.gallery-slider--wide .gs-prev { left: 1rem; }
.gallery-slider--wide .gs-next { right: 1rem; }

/* ============================================================
   PLATFORM SCORES (added 2026-08-09)
   Three review scores side by side, each in its own scale.
   The scales are deliberately printed next to every number so a
   9.7 is never mistaken for a 9.7 out of 5, and so nobody is
   tempted to average across them later.
   ============================================================ */
.platform-scores {
  list-style: none;
  margin: 1.75rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
}
.platform-scores li {
  flex: 0 1 11rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--sand);
  border-radius: var(--radius, 4px);
  background: var(--bone);
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.ps-score {
  font-family: var(--font-display);
  font-size: 1.9rem;
  line-height: 1;
  color: var(--terracotta);
}
.ps-of {
  font-family: var(--font-accent);
  font-size: 0.8rem;
  color: var(--ink-soft);
  letter-spacing: 0.04em;
}
.ps-where {
  font-family: var(--font-accent);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  margin-top: 0.35rem;
}
.ps-count {
  font-family: var(--font-accent);
  font-size: 0.72rem;
  color: var(--ink-soft);
}
.platform-note {
  font-family: var(--font-accent);
  font-size: 0.82rem;
  color: var(--ink-soft);
  max-width: 34rem;
  margin: 1rem auto 0;
}
@media (max-width: 600px) {
  .platform-scores li { flex: 1 1 8.5rem; padding: 0.85rem 1rem; }
  .ps-score { font-size: 1.6rem; }
}

/* Sub-heading inside the errands section, separating on foot from short drive. */
.errand-head {
  font-family: var(--font-accent);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--terracotta);
  margin: 2.25rem 0 0.75rem;
}

/* ---- Collapsible guide groups (santa-fe.html) ----
   Added 2026-08-30 on Andrew's ask: bigger category titles, and each
   category collapsible so the guide is scannable rather than a wall.
   The first group in each section is left open in the HTML so the page
   never reads as empty. Content inside a closed <details> is still in
   the DOM, so search engines still index every listing. */
.guide-group {
  border-top: 1px solid var(--rule, #e4d7c9);
}
.guide-group:last-of-type {
  border-bottom: 1px solid var(--rule, #e4d7c9);
}
.guide-group__head {
  font-family: var(--font-display, var(--font-accent));
  font-size: 1.5rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--ink, #241a15);
  cursor: pointer;
  list-style: none;
  padding: 1.15rem 2.5rem 1.15rem 0;
  position: relative;
  transition: color 0.15s ease;
}
.guide-group__head::-webkit-details-marker { display: none; }
.guide-group__head:hover { color: var(--terracotta); }
.guide-group__head:focus-visible {
  outline: 2px solid var(--terracotta);
  outline-offset: 3px;
}
/* the chevron */
.guide-group__head::after {
  content: "";
  position: absolute;
  right: 0.4rem;
  top: 50%;
  width: 0.6rem;
  height: 0.6rem;
  border-right: 2px solid var(--terracotta);
  border-bottom: 2px solid var(--terracotta);
  transform: translateY(-70%) rotate(45deg);
  transition: transform 0.2s ease;
}
.guide-group[open] > .guide-group__head::after {
  transform: translateY(-30%) rotate(-135deg);
}
.guide-group > .guide-list {
  margin-top: 0;
  padding-bottom: 0.75rem;
}
@media (prefers-reduced-motion: reduce) {
  .guide-group__head,
  .guide-group__head::after { transition: none; }
}
@media (max-width: 600px) {
  .guide-group__head { font-size: 1.25rem; padding-right: 2rem; }
}

/* TurboTenant availability embed. Boxed so an empty list still looks
   deliberate rather than like a hole in the page. */
.tt-embed {
  margin-top: 2rem;
  border: 1px solid var(--sand);
  border-radius: var(--radius, 4px);
  background: var(--bone);
  overflow: hidden;
}
.tt-embed iframe {
  display: block;
  width: 100%;
  border: 0;
  max-width: 100%;
}
@media (max-width: 600px) {
  .tt-embed iframe { height: 900px; }
}

/* Booking widget panel. The OwnerRez widget brings its own styling; these
   rules only govern the frame around it and the talk-to-us fallback. */
.book-panel .ownerrez-widget {
  margin: 0 auto;
  max-width: 46rem;
  text-align: left;
}
.book-alt {
  margin: 2rem 0 0.9rem;
  font-family: var(--font-accent);
  font-size: 0.85rem;
  color: var(--ink-soft);
}

/* Proof line under the hero copy on index and stay, added 2026-08-12.
   Andrew: "it should be very clear that you're gonna be booking a place that
   you're gonna absolutely love." The full widget is a long way down both
   pages, so the rating goes where people land. Quiet, not a badge. */
.proof {
  margin: 1.5rem 0 0;
  display: flex;
  align-items: center;
  gap: 0.5rem 1.25rem;
  flex-wrap: wrap;
}
.center .proof { justify-content: center; }

.proof-badges {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  font-family: var(--font-accent);
  font-size: 0.9rem;
  color: var(--ink-soft);
}
/* Recognition badges: Airbnb Superhost and the Booking.com Traveler Review
   Award 2026, confirmed from Andrew's award PDFs 2026-08-12.

   DELIBERATELY TEXT, NOT THE SUPPLIED GRAPHICS. Booking.com's own asset is a
   large flat blue panel and Airbnb's is a red badge. Dropping either onto an
   adobe and terracotta page would look like an advert someone else paid for,
   which is the opposite of what these are meant to convey. Set in the site's
   own type, they read as facts about the place rather than borrowed livery.

   THE SCORES ARE DELIBERATELY NOT HERE EITHER. Booking.com scores out of 10
   and the live widget beside these scores out of 5. Showing 9.9 and 4.97 side
   by side invites a reader to compare two different scales, which is the same
   mistake as averaging across them. The badges name the award; the widget
   carries the number. */
.badge-host {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--sand);
  border-radius: 2rem;
  background: var(--sand-light);
  color: var(--ink);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

/* The capped-preview styles that used to live here went with the OwnerRez
   reviews iframe on 2026-08-30. The homepage now renders three real reviews
   (see tools/build-reviews.py), so there is nothing left to fade out. */
.reviews-more {
  margin: 1.25rem 0 0;
  font-family: var(--font-accent);
  font-size: 0.9rem;
}

/* Reviews widget panel. Same approach as .book-panel: the OwnerRez widget
   brings its own styling, so these rules govern the frame around it and
   nudge its typography toward the site's faces rather than fighting it.
   Added 2026-08-12 when GET /v2/reviews finally returned real items. */
.reviews-panel {
  margin: 2.25rem auto 0;
  max-width: 60rem;
  text-align: left;
}
.reviews-panel .ownerrez-widget {
  font-family: var(--font-body);
  color: var(--ink);
}
/* The widget renders guest names and dates in its own default face. Pulling
   just those toward the display face ties it to the rest of the page without
   touching the review text itself, which stays exactly as the guest wrote it. */
.reviews-panel .ownerrez-widget h1,
.reviews-panel .ownerrez-widget h2,
.reviews-panel .ownerrez-widget h3,
.reviews-panel .ownerrez-widget h4 {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--ink);
}
.reviews-panel .ownerrez-widget a { color: var(--terracotta); }
.reviews-panel .ownerrez-widget a:hover { color: var(--terracotta-deep); }

/* STR permit number in the footer. Required on advertisements by the City of
   Santa Fe, so it must stay visible; quiet, but never display:none. */
.permit {
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  opacity: 0.8;
}

/* ============================================================
   STR PERMIT BADGE (added 2026-08-10)
   Andrew: "the Santa Fe STR permit, can we do something fun or
   funky with that? Maybe have it at the bottom, right there."

   So it moves out of the address block and onto the bottom bar
   as a stamped chip, which is what a permit reads as anyway.
   The City of Santa Fe requires the number on advertisements,
   so this is styling only: it stays real text, stays selectable,
   stays in the accessibility tree, and must NEVER become
   display:none, a background image, or an abbreviation.
   Update the number here and in every page footer when the
   permit renews. Active through 12/31/2026.
   ============================================================ */
.permit-badge {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid rgba(184, 91, 61, 0.75);
  border-radius: 2px;
  overflow: hidden;
  line-height: 1;
  letter-spacing: 0.1em;
  font-size: 0.62rem;
  text-transform: uppercase;
  white-space: nowrap;
}
.permit-badge-label {
  background: var(--terracotta);
  color: var(--bone);
  padding: 0.42rem 0.5rem;
  font-weight: 700;
}
.permit-badge-num {
  padding: 0.42rem 0.55rem;
  color: var(--sand);
  font-weight: 700;
  /* Tabular-ish spacing so the number reads as a stamped serial rather
     than as body copy. */
  letter-spacing: 0.14em;
}

/* ============================================================
   FLOOR PLANS (added 2026-08-10)
   Andrew asked for these four times: "you have all the layouts
   for all these, so let's figure a way to put in layouts...
   layouts are gonna be super helpful, people wanna see that."

   Cropped out of the stamped 2020 architectural set at 300 dpi.
   THE TITLE BLOCK IS DELIBERATELY CROPPED OFF EVERY ONE: it
   carries the full street address, which came off the site on
   2026-08-10. Do not re-crop these from the source without
   checking that the address is still excluded.

   Served as PNG, not JPEG. These are thin black lines on white,
   and JPEG ringing around that is exactly what makes a floor
   plan look cheap. They sit inside a <details> so they never
   cost a visitor a screen of scrolling on a phone.
   ============================================================ */
.floorplan {
  margin: 0;
  background: #FFFFFF;
  border: 1px solid var(--sand);
  border-radius: 2px;
  padding: clamp(0.75rem, 3vw, 1.5rem);
}
.floorplan img { width: 100%; height: auto; }

/* main.js wraps each plan in a real button so it is keyboard reachable.
   The button must not look like a button, only behave like one. */
.floorplan-open {
  display: block;
  width: 100%;
  padding: 0;
  margin: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}
.floorplan-open:focus-visible { outline: 2px solid var(--terracotta); outline-offset: 4px; }
/* Only promise the zoom once JavaScript has actually wired it up. */
.js-floorplan .floorplan figcaption::after {
  content: " · Tap to enlarge";
  color: var(--terracotta);
}
.floorplan figcaption {
  font-family: var(--font-accent);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-top: 0.85rem;
  text-align: center;
}

/* ============================================================
   ICONS (added 2026-08-10)
   Andrew: "I want some icons here... what about doing little
   picture icons to actually showcase each of the amenities?
   Make it attractive to the eye."

   Drawn by hand as an inline SVG sprite at the top of the page
   body, NOT loaded from an icon library. Three reasons: this is
   a static site with no build step, an external icon font or CDN
   would be a third request and a tracking surface, and a sprite
   lets Andrew reuse an icon with one short line of markup.

   They are stroke-only and inherit currentColor, so they pick up
   whatever colour their container already uses and cannot drift
   away from the brand palette. Every one is aria-hidden, because
   the text label beside it already says the same thing and a
   screen reader announcing "parking, parking" is worse than
   silence.

   TO USE ONE:  <svg class="ico" aria-hidden="true"><use href="#i-parking"/></svg>
   TO ADD ONE:  add a <symbol id="i-yourname" viewBox="0 0 24 24">
                to the sprite block in the page body.
   ============================================================ */
.ico {
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  overflow: visible;
}
.ico--lg { width: 1.75rem; height: 1.75rem; }
.ico--sm { width: 1.05rem; height: 1.05rem; stroke-width: 1.7; }

/* The quick answers block and the amenity grid both stack their icon
   above the label. Keeping the icon on its own line rather than inline
   means a long label wraps under itself instead of under the icon. */
.quick-facts .ico,
.amenity-grid .ico {
  display: block;
  color: var(--terracotta);
  margin-bottom: 0.55rem;
}

/* Specs row under the h1: bed, floor area, sleeps. Replaces a run of
   middots that read as a spec sheet. Andrew on the old version: "one
   bedroom since the, you know, I guess with the square feet, you say
   approximately 708 square feet, that's weird." */
.specs {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.75rem;
  font-family: var(--font-accent);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.specs li { display: flex; align-items: center; gap: 0.5rem; }
.specs .ico { color: var(--terracotta); }

/* ============================================================
   HUBSPOT FORM FRAME (added 2026-08-10)
   The contact form is a HubSpot embed, so HubSpot owns the field
   styling and we deliberately do not fight it. This rule only
   reserves vertical space, so the page does not jump when the
   deferred script finishes and the form appears. If the form
   grows or shrinks in HubSpot, adjust the min-height to match.
   ============================================================ */
.hs-form-frame { min-height: 32rem; }
@media (max-width: 600px) { .hs-form-frame { min-height: 36rem; } }

/* A .textlink that is the ONLY thing in its paragraph is a standalone
   control, not a link inside a sentence, so it gets a real 44px target.
   Found 2026-08-10: "Read the guest FAQ" and "Meanwhile, book on Airbnb"
   were both still rendering 18px tall on a phone after the Phase A touch
   target pass, because that pass exempted anything sitting inside a <p>.
   Links genuinely inside prose stay exempt on purpose: stretching one of
   those to 44px breaks the line spacing of the paragraph around it. */
p > .textlink:only-child {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
}

/* ============================================================
   QUICK ANSWERS (added 2026-08-10)
   The handful of things guests ask before anything else,
   answered directly under the hero instead of inside an FAQ
   accordion three pages away.

   Parking leads on purpose. It is the most asked question in
   the entire guest message history by a wide margin: 76
   mentions across 1,812 guest messages, more than double the
   next topic. Evidence and the full frequency table are in
   Box/04 Paseo Retreat/OwnerRez/DRAFT_29 section 3.
   ============================================================ */
.quick-facts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem 2rem;
}
/* Each answer takes a different accent, cycling terracotta, turquoise,
   indigo, gold. Sampled from the casita's own textiles, so the row reads as
   the Navajo rug rather than as a set of random colours. The rule uses
   :nth-child so it keeps working however many answers Andrew adds. */
.quick-facts li { border-top: 2px solid var(--terracotta); padding-top: 0.85rem; }
.quick-facts li:nth-child(4n+2) { border-top-color: var(--turquoise); }
.quick-facts li:nth-child(4n+3) { border-top-color: var(--indigo); }
.quick-facts li:nth-child(4n+4) { border-top-color: var(--gold); }
.quick-facts li:nth-child(4n+2) .ico,
.quick-facts li:nth-child(4n+2) strong { color: var(--turquoise); }
.quick-facts li:nth-child(4n+3) .ico,
.quick-facts li:nth-child(4n+3) strong { color: var(--indigo); }
.quick-facts li:nth-child(4n+4) .ico,
.quick-facts li:nth-child(4n+4) strong { color: var(--gold); }

/* Same cycle on the amenity icons, which is where the page has the most
   repetition and the least colour. Titles stay ink so the grid still reads
   as a list rather than as a rainbow. */
.amenity-grid li:nth-child(4n+2) .ico { color: var(--turquoise); }
.amenity-grid li:nth-child(4n+3) .ico { color: var(--indigo); }
.amenity-grid li:nth-child(4n+4) .ico { color: var(--gold); }
.quick-facts strong {
  display: block;
  font-family: var(--font-accent);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--terracotta);
  margin-bottom: 0.4rem;
}
.quick-facts span { display: block; font-size: 0.95rem; line-height: 1.55; color: var(--ink); }

@media (max-width: 900px) { .quick-facts { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .quick-facts { grid-template-columns: 1fr; gap: 1.25rem; } }

/* ============================================================
   DISCLOSURE (added 2026-08-10)
   Andrew: "Delete material, and hide some detail behind
   expandable sections."

   This is NOT the .faq-group accordion. That one is a stacked
   list of many questions; this is a single inline toggle that
   sits inside a section and holds detail worth keeping but not
   worth a screen of scrolling on a phone.

   Everything inside stays in the DOM and stays reachable by
   search, screen reader and Cmd+F, because <details> is a real
   element rather than a JavaScript show/hide. The summary is a
   44px touch target, matching the rest of the site.
   ============================================================ */
.disclose {
  border-top: 1px solid var(--sand);
  border-bottom: 1px solid var(--sand);
  margin: 2rem 0 0;
}
.disclose > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1.5rem;
  min-height: 2.75rem;
  padding: 0.9rem 0;
  font-family: var(--font-accent);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--terracotta);
}
.disclose > summary::-webkit-details-marker { display: none; }
/* A plus that rotates into a cross when open. No dash characters
   anywhere in this file's content, per the house style rule. */
.disclose > summary::after {
  content: "+";
  font-family: var(--font-body);
  font-size: 1.5rem;
  font-weight: 400;
  line-height: 1;
  transition: transform 0.2s ease;
}
.disclose[open] > summary::after { transform: rotate(45deg); }
.disclose > .disclose-body { padding: 0.25rem 0 1.75rem; }
.disclose > .disclose-body > :last-child { margin-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .disclose > summary::after { transition: none; }
}

/* ---------- guest reviews (stay.html), added 2026-08-30 ----------
   These replaced the OwnerRez reviews iframe. The markup is generated by
   tools/build-reviews.py, so class names here and in that script have to
   stay in step. See the header of that file for why the iframe went.

   The section is .container.center, so the list resets text-align to left:
   centred paragraphs of 1,600 characters are unreadable. */
.rv-summary {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: center; gap: 0.5rem;
  margin: 1.75rem 0 0; font-family: var(--font-body);
}
.rv-avg { font-family: var(--font-display); font-size: 2.25rem; line-height: 1; color: var(--ink); }
.rv-stars { color: var(--terracotta); letter-spacing: 0.08em; }
.rv-count { color: var(--ink-soft); font-size: 0.95rem; }

.rv-list {
  list-style: none; margin: 2.5rem 0 0; padding: 0; text-align: left;
  display: grid; gap: 1.5rem;
}
@media (min-width: 900px) { .rv-list { grid-template-columns: 1fr 1fr; gap: 1.5rem 2.5rem; } }

.rv-item {
  border-top: 1px solid var(--sand); padding-top: 1.25rem;
  break-inside: avoid;
}
.rv-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem;
  margin-bottom: 0.5rem; font-size: 0.9rem;
}
.rv-by { font-weight: 700; color: var(--ink); }
.rv-date { color: var(--muted); }
.rv-title {
  font-family: var(--font-display); font-size: 1.15rem;
  margin: 0 0 0.35rem; color: var(--ink);
}
.rv-body p { margin: 0 0 0.75rem; color: var(--ink-soft); font-size: 0.95rem; line-height: 1.65; }
.rv-body p:last-child { margin-bottom: 0; }

.rv-more { margin-top: 2rem; }
.rv-more > summary {
  cursor: pointer; display: inline-block; font-family: var(--font-body);
  font-size: 0.95rem; color: var(--terracotta); padding: 0.5rem 0;
}
.rv-more > summary:hover { color: var(--terracotta-deep); }
.rv-more[open] > summary { margin-bottom: 0.5rem; }

/* Visually hidden but read aloud. The star glyphs are aria-hidden, so this
   is the only thing a screen reader gets for a rating. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Andrew's public reply to a review. Set in from the review it answers so the
   two read as a conversation rather than one long block of guest text. */
.rv-reply {
  margin-top: 0.85rem;
  padding-left: 0.9rem;
  border-left: 2px solid var(--sand);
}
.rv-reply-by {
  display: block;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--terracotta);
  margin-bottom: 0.3rem;
}
.rv-reply p { margin: 0 0 0.6rem; color: var(--ink-soft); font-size: 0.9rem; line-height: 1.6; }
.rv-reply p:last-child { margin-bottom: 0; }

/* The "leave a review" ask under the guest reviews on stay.html. Quiet on
   purpose: it sits below 54 reviews and should read as an invitation, not a
   second call to action competing with the booking widget. */
.rv-ask {
  margin: 2.5rem 0 0;
  font-size: 0.95rem;
  color: var(--ink-soft);
}
