/* ===========================================================================
   oldfarmter.us — structural stylesheet

   Layout and rhythm only: enough that the skeleton reads as a page, not a
   design. Colours come from tokens.css; nothing here hard-codes one.

   Class names that are NOT free to rename — availability-calendar.js looks
   for them when it walks out from a calendar to find the booking widget it
   should drive:

     .booking-split      wraps a calendar and its booking widget together
     .booking-panel      the dark surface the booking widget sits on
     .property-detail    alternative scope, for a per-property page
   =========================================================================== */

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--surface-alt);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

h1, h2, h3 {
  font-family: var(--font-display), Georgia, serif;
  font-weight: 500;
  line-height: 1.15;
  color: var(--brand-deep);
  margin: 0 0 0.5em;
}

h1 { font-size: clamp(2rem, 5vw, 3.25rem); }
h2 { font-size: clamp(1.5rem, 3vw, 2.125rem); }
h3 { font-size: 1.125rem; }

p { margin: 0 0 1rem; max-width: var(--measure); }

a { color: var(--brand); }
a:focus-visible,
button:focus-visible,
.ac-day:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

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

/* --- skip link ----------------------------------------------------------- */

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--surface);
  color: var(--brand-deep);
  padding: 0.75rem 1rem;
  z-index: 10;
}
.skip-link:focus { left: 0; }

/* --- shell --------------------------------------------------------------- */

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

.site-header {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.site-header .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 1rem;
}

/* A stacked lockup — illustration over wordmark — so it needs real height to
   stay legible: below roughly 56px the "FARMHOUSE RETREAT" line stops reading.
   Height drives the size and width follows from the intrinsic width/height on
   the <img>, which also reserves the space before the file loads. */
.brandmark {
  display: flex;
  align-items: center;
  line-height: 0; /* no descender gap beneath an inline image */
}

.brandmark img {
  display: block;
  height: 80px;
  width: auto;
}

.site-nav { display: flex; flex-wrap: wrap; gap: 0.25rem 1.25rem; }
.site-nav a {
  color: var(--text-light);
  text-decoration: none;
  font-size: 0.9375rem;
  padding-block: 0.25rem; /* tap height without adding width */
}
.site-nav a:hover { color: var(--brand); }

.section { padding-block: var(--section-y); }
.section-alt { background: var(--surface-warm); }
.section > .wrap > :first-child { margin-top: 0; }

.site-footer {
  background: var(--brand-deep);
  color: var(--text-invert);
  padding-block: 2.5rem;
}
.site-footer a { color: var(--text-invert); }

/* --- booking: calendar beside the OwnerRez widget ------------------------ */

.booking-split {
  display: grid;
  grid-template-columns: minmax(320px, 1fr) minmax(320px, 1fr);
  gap: 1.5rem;
  align-items: start;
}

@media (max-width: 900px) {
  .booking-split { grid-template-columns: 1fr; }
}

/* Narrow screens. The logo and five nav items cannot share a row here, so the
   nav takes its own — the aim is for that to read as a deliberate second row
   rather than the last item falling off the end of the first.

   Centred, because a left-aligned logo leaves the rest of the row empty and the
   header then reads as two ragged fragments. Tighter type and gaps are what get
   all five items onto one line on a 390px phone; below about 360px they wrap to
   two, which is why the row-gap is set rather than left to chance. */
@media (max-width: 640px) {
  .site-header .wrap {
    justify-content: center;
    gap: 0.5rem;
    padding-block: 0.75rem;
  }

  .brandmark img { height: 48px; }

  .site-nav {
    width: 100%;
    justify-content: center;
    gap: 0.375rem 0.875rem;
  }

  .site-nav a { font-size: 0.875rem; }
}

/* Dark on purpose. One widget id serves every placement and gets one CSS box,
   so the booking widget's labels are a single colour everywhere on the site —
   widget-css/booking-inquiry.css assumes they sit on a dark surface. Making
   this light means inverting that stylesheet too (docs/setup.md, step 6). */
.booking-panel {
  background: var(--brand-deep);
  border-radius: var(--radius);
  padding: 1.25rem;
  min-height: 320px;
}

/* --- reviews (rendered from /api/reviews as indexable markup) ------------ */

.reviews-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1rem;
  padding: 0;
  margin: 0;
  list-style: none;
}

.review {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem;
}
.review p { margin-bottom: 0.5rem; }
.review footer { color: var(--text-light); font-size: 0.875rem; }

.rating-summary { font-size: 1.0625rem; }
.rating-summary strong { color: var(--brand-deep); }

/* --- placeholder scaffolding (delete once the design lands) -------------- */

.placeholder {
  border: 1px dashed var(--accent);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-light);
  padding: 2rem 1.25rem;
  text-align: center;
  font-size: 0.9375rem;
}

/* --- gallery (rendered from the manifest by assets/js/gallery.js) --------- */

.gallery-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1rem;
}

.gallery-grid li {
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

/* A fixed ratio so the grid does not reflow as each image arrives. */
.gallery-grid img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--surface-warm);
}

.gallery-grid figcaption {
  padding: 0.625rem 0.75rem;
  font-size: 0.875rem;
  color: var(--text-light);
}

/* --- email signup -------------------------------------------------------- */

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.subscribe {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  max-width: var(--measure);
}

.subscribe input[type="email"] {
  flex: 1 1 15rem;
  font: inherit;
  padding: 0.625rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
}

.subscribe button {
  font: inherit;
  padding: 0.625rem 1.25rem;
  cursor: pointer;
  border: 1px solid var(--brand);
  border-radius: var(--radius-sm);
  background: var(--brand);
  color: var(--text-invert);
}
.subscribe button:disabled { opacity: 0.6; cursor: default; }

/* Full width so a message never squeezes the field onto a second line. */
.subscribe-status { flex: 1 0 100%; margin: 0; font-size: 0.875rem; }
.subscribe-status:empty { display: none; }
.subscribe-status[data-state="bad"] { color: #b91c1c; }

.fine-print { font-size: 0.875rem; color: var(--text-light); }

/* --- analytics consent --------------------------------------------------- */

.consent {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.75rem 1.5rem;
  padding: 1rem var(--gutter);
  background: var(--brand-deep);
  color: var(--text-invert);
  /* The bar sits above the page rather than pushing it, so a shadow is what
     separates the two. */
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.18);
}

.consent p {
  margin: 0;
  max-width: 60ch;
  font-size: 0.875rem;
  line-height: 1.5;
}

.consent a { color: var(--text-invert); }

.consent-actions { display: flex; gap: 0.5rem; }

.consent button {
  font: inherit;
  font-size: 0.875rem;
  padding: 0.5rem 1.25rem;
  cursor: pointer;
  border-radius: var(--radius-sm);
  /* Comfortably past the 44px minimum once padding and line-height are counted,
     because this is the first thing a thumb meets on a phone. */
  min-height: 2.75rem;
}

.consent-accept {
  background: var(--surface);
  color: var(--brand-deep);
  border: 1px solid var(--surface);
}

/* Declining is given equal weight rather than being hidden as faint text: a
   choice that is hard to find is not much of a choice. */
.consent-decline {
  background: transparent;
  color: var(--text-invert);
  border: 1px solid rgba(255, 255, 255, 0.55);
}
.consent-decline:hover { border-color: var(--text-invert); }

@media (max-width: 640px) {
  .consent { flex-direction: column; text-align: center; }
  .consent-actions { width: 100%; }
  .consent-actions button { flex: 1; }
}
