/* ==========================================================================
   home.css — Hunter Huon Valley
   Section-specific styles for the homepage. All values from tokens.css.
   ========================================================================== */

/* --- Header -------------------------------------------------------------- */

.site-header {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--z-header);
  background-color: transparent;
  color: var(--color-text-on-dark);
  transition: background-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
/* Soft top-down gradient behind the transparent header so nav links stay
   legible over photography. Fades out once the header goes solid. */
.site-header::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: calc(var(--header-h) * 2);
  background-image: var(--scrim-header);
  pointer-events: none;
  z-index: 0;
  transition: opacity var(--dur-fast) var(--ease);
}
.site-header.is-scrolled::before { opacity: 0; }

.site-header__inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  min-height: var(--header-h);
}
/* Desktop: three even tracks — brand left, nav centred, CTA right — so the bar
   stays balanced regardless of the wordmark or button width. */
@media (min-width: 900px) {
  .site-header__inner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
  }
  .nav { justify-self: center; }
  /* Match the CTA's outer box to the wordmark (152 x 38) so the two ends of
     the header are the same size and the bar reads symmetric. */
  .header-cta {
    justify-self: end;
    box-sizing: border-box;
    width: 152px;
    height: 38px;
    padding-block: 0;
    padding-inline: var(--space-2xs);
    letter-spacing: 0.06em;
    white-space: nowrap;
  }
}

/* Solid state once scrolled past the hero fold — solidifies to Forest with
   off-white links. The wordmark PNG is off-white only (no dark variant), so the
   scrolled header stays dark to keep it legible. See DECISIONS.md. */
.site-header.is-scrolled {
  background-color: var(--c-forest);
  color: var(--color-text-on-dark);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
}
/* Full stacked wordmark, sized by height so it keeps clear space top and
   bottom inside the 72px header. The source PNG is white and the header stays
   dark (transparent over the hero, Olive when solid), so it reads white. */
.brand__mark {
  height: 38px;
  width: auto;
}

/* Primary nav */
.nav {
  display: none;
}
@media (min-width: 900px) {
  .nav { display: flex; align-items: center; gap: var(--space-md); }
}

.nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}
.nav__link,
.nav__toggle {
  white-space: nowrap;
}
.nav__link {
  font-size: var(--fs-small);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.02em;
  padding-block: var(--space-2xs);
  border-bottom: var(--divider-w) solid transparent;
  transition: border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.nav__link:hover,
.nav__link:focus-visible {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}

/* Stay dropdown */
.nav__item--has-menu { position: relative; }
.nav__toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3xs);
  font-size: var(--fs-small);
  color: inherit;
}
.nav__toggle::after {
  content: "";
  width: 0.5em; height: 0.5em;
  border-right: var(--divider-w) solid currentColor;
  border-bottom: var(--divider-w) solid currentColor;
  transform: rotate(45deg) translateY(-2px);
  transition: transform var(--dur-fast) var(--ease);
}
.nav__toggle[aria-expanded="true"]::after {
  transform: rotate(-135deg) translateY(-1px);
}

.nav__dropdown {
  position: absolute;
  inset-block-start: calc(100% + var(--space-2xs));
  inset-inline-start: 0;
  min-width: 200px;
  display: grid;
  gap: var(--space-3xs);
  padding: var(--space-sm);
  background-color: var(--color-page-bg);
  color: var(--color-text);
  border: var(--divider-w) solid var(--color-band-alt);
  border-radius: var(--radius);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease),
              visibility var(--dur-fast) var(--ease);
}
.nav__item--has-menu .nav__dropdown.is-open {
  opacity: 1;
  visibility: visible;
  transform: none;
}
.nav__dropdown a {
  font-size: var(--fs-small);
  padding: var(--space-3xs) var(--space-2xs);
  border-radius: var(--radius-sm);
}
.nav__dropdown a:hover,
.nav__dropdown a:focus-visible { color: var(--color-accent); }

/* Header CTA always visible, and a touch smaller than the standard button so
   it sits comfortably against the wordmark rather than dominating the bar. */
.header-cta {
  flex-shrink: 0;
  padding: var(--space-2xs) var(--space-sm);
  font-size: var(--fs-eyebrow);
}
@media (max-width: 899px) {
  .header-cta { display: none; }
}

/* Hamburger */
.hamburger {
  display: inline-flex;
  flex-direction: column;
  gap: 5px;
  padding: var(--space-2xs);
}
@media (min-width: 900px) { .hamburger { display: none; } }
.hamburger span {
  width: 24px; height: 2px;
  background-color: currentColor;
  transition: transform var(--dur-fast) var(--ease),
              opacity var(--dur-fast) var(--ease);
}

/* Mobile full-screen menu */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: var(--z-mobile-menu);
  background-color: var(--color-band-dark);
  color: var(--color-text-on-dark);
  display: flex;
  flex-direction: column;
  padding: var(--space-xl) var(--gutter) var(--space-2xl);
  transform: translateY(-100%);
  visibility: hidden;
  transition: transform var(--dur-fast) var(--ease),
              visibility var(--dur-fast) var(--ease);
  overflow-y: auto;
}
.mobile-menu.is-open { transform: none; visibility: visible; }
.mobile-menu__close {
  align-self: flex-end;
  color: var(--color-text-on-dark);
  font-size: 1.5rem;
  line-height: 1;
  padding: var(--space-2xs);
}
.mobile-menu__list {
  display: grid;
  gap: var(--space-sm);
  margin-block-start: var(--space-lg);
}
.mobile-menu__list a {
  font-size: 1.375rem;
  font-weight: var(--fw-light);
}
.mobile-menu__list a:hover,
.mobile-menu__list a:focus-visible { color: var(--color-accent); }
.mobile-menu__phone {
  font-weight: var(--fw-medium);
  color: var(--color-accent-text);
}
.mobile-menu__sub {
  margin-inline-start: var(--space-md);
  display: grid;
  gap: var(--space-2xs);
}
.mobile-menu__sub a { font-size: 1.0625rem; }

/* Persistent mobile bottom booking bar */
.booking-bar {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: var(--z-bottom-bar);
  padding: var(--space-2xs) var(--gutter)
           calc(var(--space-2xs) + env(safe-area-inset-bottom, 0px));
  background-color: var(--color-band-dark);
  display: flex;
}
.booking-bar .btn { flex: 1; }
@media (min-width: 900px) { .booking-bar { display: none; } }

/* --- Hero ---------------------------------------------------------------- */

.hero {
  position: relative;
  /* Was 100svh. Trimmed a little so the booking card docked at the seam sits
     fully in view on load rather than half below the fold. */
  min-height: 90svh;
  display: flex;
  /* Anchor the title/sub to the top (below the fixed header) rather than the
     bottom, so the lower half of the photo — the stone bath — stays clear of
     the text. */
  align-items: flex-start;
  overflow: hidden;
}
.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
/* The <img> is wrapped in a <picture>. Globally picture is height:auto, so on
   tall viewports it collapses to the image's own height and leaves olive below
   the photo. Force the wrapper to fill so object-fit/position on the img work. */
.hero__media picture {
  display: block;
  width: 100%;
  height: 100%;
}
.hero__media img,
.hero__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Bias the crop toward the foot of the frame so the stone bath and its timber
     ledge sit a little higher, without pulling all the way to the bottom. */
  object-position: center 54%;
}
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background-image: var(--scrim-hero);
}
.hero__content {
  position: relative;
  z-index: 2;
  color: var(--color-text-on-dark);
  /* Clear the fixed 72px header, then a small gap, so the copy sits high in the
     frame and leaves the bath visible below. */
  padding-block-start: calc(var(--header-h) + var(--space-lg));
  padding-block-end: var(--space-2xl);
  /* Revision 2: the 40rem cap squeezed the H1 into a narrow column. Let it run
     across the page (~1100px) while the sub-line stays capped. */
  max-width: 1100px;
}
.hero__content h1 {
  color: var(--color-text-on-dark);
  /* Weight and size both come from the base h1 rule (Medium 500, --fs-h1). */
  /* 15ch was too tight for this line: "accommodation" alone is 13ch, so the cap
     forced it onto its own line and orphaned "Luxury". 24ch fits a full opening
     phrase ("Luxury accommodation in"), then text-wrap: balance (set on base h1)
     evens the remaining lines. Because the cap is in ch it scales with the font,
     so the word grouping stays consistent across breakpoints. */
  max-width: 24ch;
  margin-block: var(--space-sm);
}
/* No hero-specific size bump. A 10% desktop bump was tried and removed: at 88px
   the headline broke to FOUR lines and orphaned "Luxury" on its own, taking 42%
   of the hero. At the plain token (80px max) it sets in three balanced lines.
   text-wrap: balance drives the wrap here, not the 24ch cap, so size is the only
   lever that changes the line count. */
/* Sub-heading under the H1 — Montserrat, 19px, Medium 500. */
.hero__sub {
  font-size: 1.1875rem;
  font-weight: var(--fw-medium);
  color: var(--color-text-on-dark-alt);
  max-width: 38rem;
}
/* On desktop the sub-line reads as one unbroken row; the 38rem cap and any
   wrap only apply below 900px where the viewport is too narrow to fit it. */
@media (min-width: 900px) {
  .hero__sub {
    max-width: none;
    white-space: nowrap;
  }
}

/* --- Booking search dock -------------------------------------------------
   The Lodgify portable search bar renders its own white, shadowed card
   (themed via the --ldg-* vars below; primary = our Gold #c6952e). We float
   that card so it straddles the seam between the hero photo and the valley
   section — top half over the photo, bottom half over Olive (the page + band
   are both Olive, so the lower half always lands on Olive). Below 900px the
   widget stacks tall, so we drop the straddle and let it sit in flow. */

/* Lodgify widget theming — scoped custom properties the embed reads. Kept in
   the stylesheet (not inline) so all colour lives in CSS, per the site rule. */
:root {
  --ldg-psb-background: #F7F4EE;
  --ldg-psb-border-radius: 0.42em;
  --ldg-psb-box-shadow: 0 24px 54px 0 rgba(0, 0, 0, 0.18);
  --ldg-psb-padding: 14px;
  --ldg-psb-input-background: #F7F4EE;
  --ldg-psb-button-border-radius: 3.58em;          /* pill button */
  --ldg-psb-color-primary: var(--c-forest);        /* Forest, matches the page below */
  --ldg-psb-color-primary-lighter: #414a38;        /* lighter forest (hover/tint) */
  --ldg-psb-color-primary-darker: #1f2419;         /* darker forest (active/hover)*/
  --ldg-psb-color-primary-contrast: #F7F4EE;       /* off-white pill text         */
  --ldg-semantic-color-primary: var(--c-forest);
  --ldg-semantic-color-primary-lighter: #414a38;
  --ldg-semantic-color-primary-darker: #1f2419;
  --ldg-semantic-color-primary-contrast: #F7F4EE;
  --ldg-component-modal-z-index: 999;
}
#lodgify-search-bar { width: 100%; }

/* The Lodgify embeds inject their own stylesheet (Source Sans Pro) via hashed
   emotion classes we don't control. Family only is forced back to Montserrat so
   the booking dock doesn't read as a third-party bolt-on; sizes, weights and
   layout are left entirely to the widget. Reverse: delete these two rules. */
#lodgify-search-bar, #lodgify-search-bar *,
#lodgify-search-widget, #lodgify-search-widget * {
  font-family: var(--font-primary);
}

.booking-dock {
  position: relative;
  z-index: 6;                         /* above the hero content */
  /* Default: the card sits in flow just below the hero, on Olive. This is the
     state for phones, tablets AND laptops narrower than 1240px, because the
     Lodgify widget only collapses to a short single-row bar at ~1240px — below
     that it is a tall stacked form that would look wrong poking into the hero. */
  margin-block-start: var(--space-xl);
}
.booking-dock__card {
  width: min(100%, 62rem);
  margin-inline: auto;
  min-height: 76px;                   /* reserve height to avoid a load jump */
}
/* Straddle only once the widget is a short horizontal bar (its own viewport
   breakpoint is ~1240px). Then it's ~84px tall and lifting it -40px lands it
   half over the hero photo, half over Olive. */
@media (min-width: 1240px) {
  .booking-dock {
    margin-block-start: -40px;
  }
}

/* --- Inset split ---------------------------------------------------------
   The copy-plus-inset-photo band. Text in the wider column, a single portrait
   photo in the narrower one. On desktop the two columns are vertically centred
   so the compact copy sits level with the middle of the image, which keeps the
   band short top to bottom. The photo fits *inside* its column (rounded
   corners, the band colour showing around all four edges) rather than bleeding
   to the section edge.

   Formerly `.positioning__*`, which is how it is still named in the contact.css
   comment and the DECISIONS log. Promoted to a shared block in Rev 6 when the
   two full-bleed `.split` bands (#disconnect, #land) were converted onto it.
   Used by #positioning, #disconnect and #land. */

.inset-split__grid {
  display: grid;
  gap: var(--space-2xl);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 900px) {
  /* Copy takes the wider column; the portrait photo sits in the narrower one so
     the text has room to breathe instead of being squeezed beside a big square. */
  .inset-split__grid { grid-template-columns: 7fr 5fr; gap: var(--space-3xl); }
  /* Flip variant: photo left, copy right, so consecutive bands alternate down
     the page. Placed by grid column rather than DOM order, so the markup keeps
     copy-then-media and the single-column mobile stack is unaffected (copy
     always leads on mobile). */
  .inset-split--flip { grid-template-columns: 5fr 7fr; }
  .inset-split--flip .inset-split__media { grid-column: 1; grid-row: 1; }
  .inset-split--flip .inset-split__body  { grid-column: 2; grid-row: 1; }
}
.inset-split__body { max-width: 60ch; }
.inset-split__body > * + * { margin-block-start: var(--space-md); }
.inset-split__body h2 { margin-block-end: var(--space-lg); }

.inset-split__media {
  border-radius: var(--radius);
  overflow: hidden;
  aspect-ratio: 4 / 5;
}
/* The <img> is wrapped in <picture>, which is globally height:auto, so inside
   this 4:5 box it collapses to the image's own height and overflow just clips
   the bottom, ignoring object-position. Force the wrapper to fill the box, the
   same fix `.amenities__media picture` carries. */
.inset-split__media picture { display: block; width: 100%; height: 100%; }
.inset-split__media img { width: 100%; height: 100%; object-fit: cover; object-position: center; }

/* --- Cabin cards --------------------------------------------------------- */

.cabins__intro { margin-block-end: var(--space-2xl); } /* left-aligned (Rev 2) */

.cabin-grid {
  display: grid;
  gap: var(--space-xl);
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .cabin-grid { grid-template-columns: repeat(3, 1fr); gap: var(--space-lg); }
}

.cabin-card { display: flex; flex-direction: column; }
.cabin-card__media {
  overflow: hidden;
  border-radius: var(--radius);
  aspect-ratio: 4 / 5;
}
.cabin-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-mid) var(--ease);
}
.cabin-card:hover .cabin-card__media img,
.cabin-card:focus-within .cabin-card__media img { transform: scale(1.03); }

.cabin-card__body { padding-block-start: var(--space-md); }
.cabin-card__title { margin-block-end: var(--space-2xs); }
.cabin-card__title a { transition: color var(--dur-fast) var(--ease); }
.cabin-card:hover .cabin-card__title a { color: var(--color-accent); }
.cabin-card__feel { color: var(--color-text-secondary); margin-block-end: var(--space-sm); }
.cabin-card__price {
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  margin-block-end: var(--space-xs);
}
.cabin-card__placeholder {
  color: var(--color-text-secondary);
}

.cabins__foot {
  color: var(--color-text-secondary);
  margin-block-start: var(--space-2xl);
  max-width: 48ch;
}
@media (min-width: 900px) {
  .cabins__foot { max-width: none; }
}

/* Reassurance callout */
.callout {
  margin-block-start: var(--space-lg);
  padding: var(--space-md);
  background-color: var(--color-band-alt);
  border-radius: var(--radius);
  font-size: var(--fs-small);
}
/* On a dark band the callout uses a translucent light panel, off-white text */
.band--dark .callout {
  background-color: var(--overlay-on-dark);
  color: var(--color-text-on-dark-alt);
}

/* Quiet reassurance note: small, muted. No panel; it sits inline as a soft
   aside under the copy (used in the Why Hunter band). */
.note-quiet {
  margin-block-start: var(--space-lg);
  font-size: var(--fs-small);
  color: var(--color-text-on-dark-alt);
  opacity: .7;
}

/* Why Hunter photo: the 2:3 original cropped to the block's 4:5 frame loses
   ~17% of its height. The cabin sits low in this frame, under a large flat
   grey sky, so anchor the crop to the bottom: the whole loss comes off the
   empty sky and the tree ferns stay whole at the base. */
#disconnect .inset-split__media img { object-position: center bottom; }

/* Land pull-quote: an editorial guest quote inside the light band. Kept
   quiet and on-brand — a single hairline Copper rule as the accent (Copper is
   accent-only), italic Forest text, and a small Olive attribution using the
   site's middot separators. No review schema. */
.land-quote {
  margin-block: var(--space-lg);
  padding-inline-start: var(--space-md);
  border-inline-start: 2px solid var(--c-copper);
}
.land-quote blockquote {
  margin: 0;
  font-family: var(--font-primary);
  font-weight: var(--fw-light);
  font-size: clamp(1.125rem, 0.6vw + 1rem, 1.375rem);
  line-height: 1.5;
  color: var(--color-text-on-light);
}
.land-quote figcaption {
  margin-block-start: var(--space-sm);
  font-size: var(--fs-small);
  font-style: normal;
  color: var(--color-text-on-light-2);
}
.land-quote figcaption span { color: var(--c-copper); }

/* --- Review proof banner -------------------------------------------------
   Compact off-white strip that sits between the positioning and cabins olive
   bands. Reuses the shared gold .stars component. Numbers use tabular figures
   so they read as data. On desktop a hairline Copper rule (accent-only) sets
   the stars off from the caption, echoing the .land-quote treatment. */
.review-banner { padding-block: var(--space-xl); }
.review-banner__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  text-align: center;
}
/* Left group: stars with the numeric score beside them. */
.review-banner__figure {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2xs) var(--space-md);
}
.review-banner__score {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-2xs);
  color: var(--color-text-on-light);
}
/* Same treatment as the reviews summary score, a step smaller. */
.review-banner__value {
  font-size: clamp(1.75rem, 3vw, 2.25rem);
  font-weight: var(--fw-light);
  letter-spacing: var(--ls-h2);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.review-banner__outof {
  font-size: var(--fs-small);
  color: var(--color-text-on-light-2);
}
.review-banner__lead {
  font-size: var(--fs-h3);
  font-weight: var(--fw-light);
  line-height: 1.4;
  color: var(--color-text-on-light);
  max-width: 44ch;
}
.review-banner__num {
  font-weight: var(--fw-medium);
  font-variant-numeric: tabular-nums;
}
@media (min-width: 720px) {
  .review-banner__inner {
    flex-direction: row;
    justify-content: center;
    gap: var(--space-lg);
  }
  .review-banner__lead {
    text-align: start;
    max-width: 40ch;
    padding-inline-start: var(--space-lg);
    border-inline-start: 2px solid var(--c-copper);
  }
}

/* --- Reviews -------------------------------------------------------------
   A light proof band with Forest text: a gold-star rating summary above an
   auto-scrolling marquee of guest cards. Stars are inline SVG filled with
   harvest Gold and given a deeper-gold hairline edge so they read crisply on
   the off-white band. No review schema anywhere — star ratings live on Google.

   The marquee loops continuously (CSS transform) and pauses on hover/focus.
   The track holds two identical .review-set groups; translating it by -50%
   lands the duplicate exactly where the original began, so the loop is seam-
   less. Under prefers-reduced-motion the animation stops and the band becomes
   a normal horizontally scrollable row (duplicate set hidden). */

/* Shared gold star component (summary + cards) */
.stars {
  display: inline-flex;
  gap: 3px;
  line-height: 0;
}
.stars svg {
  width: 18px; height: 18px;
  display: block;
  fill: var(--color-star);
  stroke: var(--color-star-edge);
  stroke-width: 0.75;
  vector-effect: non-scaling-stroke;
}
.stars--lg svg { width: 26px; height: 26px; }

/* Section header — a centred editorial lockup that sits above the marquee.
   eyebrow, title, then the star rating as one cohesive unit. */
.reviews__head {
  text-align: center;
  max-width: 48rem;
  margin-inline: auto;
  margin-block-end: var(--space-2xl);
}
.reviews__head .eyebrow { margin-block-end: var(--space-sm); }
.reviews__title {
  margin-block: var(--space-2xs) var(--space-lg);
}

/* Rating lockup — stars and score read as a single object, not two stacked
   pieces. The score is sized to sit beside the stars rather than tower over
   them, so it never looks out of place. */
.rating {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-md);
}
.rating--lockup {
  justify-content: center;
  gap: var(--space-sm);
}
.rating__score {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-2xs);
  color: var(--color-text-on-light);
  font-variant-numeric: tabular-nums;
}
.rating__value {
  font-family: var(--font-primary);
  font-size: clamp(1.5rem, 3.2vw, 2rem);
  font-weight: var(--fw-light);
  letter-spacing: var(--ls-h2);
  line-height: 1;
}
.rating__outof {
  font-size: var(--fs-body);
  color: var(--color-text-on-light-2);
}

/* Footer proof line — moved below the cards. Reads as quiet supporting
   context; the numbers are emphasised, the CTA is the action. */
.reviews__foot {
  margin-block-start: var(--space-2xl);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  text-align: center;
}
.reviews__stat {
  margin: 0;
  font-size: var(--fs-body);
  font-weight: var(--fw-regular);
  line-height: 1.5;
  color: var(--color-text-on-light-2);
  max-width: 46ch;
}
.reviews__stat-num {
  color: var(--color-text-on-light);
  font-weight: var(--fw-medium);
  font-variant-numeric: tabular-nums;
}

/* Marquee */
.review-marquee {
  position: relative;
  overflow: hidden;
  /* Soft fade at both edges so cards enter and leave gracefully */
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 6%, #000 94%, transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, #000 6%, #000 94%, transparent 100%);
}
.review-track {
  display: flex;
  width: max-content;
  padding-block: var(--space-3xs) var(--space-sm);
  animation: review-marquee 85s linear infinite;
}
/* Pause when the guest wants to read */
.review-marquee:hover .review-track,
.review-marquee:focus-within .review-track {
  animation-play-state: paused;
}
.review-set {
  display: flex;
  gap: var(--space-lg);
  padding-inline-end: var(--space-lg); /* trailing gap keeps the loop even */
}

@keyframes review-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.review-card {
  flex: 0 0 min(85vw, 22rem);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-lg);
  background-color: var(--c-base);
  border-radius: var(--radius);
}
/* The section band IS --c-base, so give cards a hair of separation via a very
   soft inset ring rather than a heavy border. */
.band--light .review-card { box-shadow: inset 0 0 0 1px var(--ring-on-light); }

.review-card__head {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}
.review-card__avatar {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background-color: var(--c-forest);
  color: var(--c-base);
  font-weight: var(--fw-medium);
  font-size: 1.0625rem;
}
.review-card__name {
  font-weight: var(--fw-medium);
  color: var(--color-text-on-light);
  line-height: 1.2;
}
.review-card__meta {
  display: block;
  font-size: var(--fs-small);
  color: var(--color-text-on-light-2);
}
.review-card__text {
  color: var(--color-text-on-light);
  font-size: var(--fs-body);
  line-height: 1.6;
  max-width: none;
}
/* Marker-pen highlight — Sandstone behind Forest text, restyled <mark> */
.review-card__text mark {
  background-color: var(--color-highlight-bg);
  color: var(--color-highlight-text);
  padding: 0 0.15em;
  border-radius: var(--radius-sm);
}

.reviews__cta { margin-block-start: var(--space-2xs); }

/* Reduced motion: stop the loop, hide the duplicate, allow a manual scroll. */
@media (prefers-reduced-motion: reduce) {
  .review-marquee {
    overflow-x: auto;
    -webkit-mask-image: none;
            mask-image: none;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .review-marquee::-webkit-scrollbar { display: none; }
  .review-track {
    animation: none;
    width: auto;
  }
  .review-set[aria-hidden="true"] { display: none; }
}

/* --- Amenities -----------------------------------------------------------
   Left-aligned, on Olive, with a supporting photograph beside a ruled spec
   list. Each amenity is a row with a consistent Sandstone line icon and a
   hairline divider, so the list reads as a deliberate spec sheet rather than
   free-floating text. Copper stays reserved for accents. */

/* Tighter vertical rhythm — this section reads as a compact spec panel, so it
   doesn't need the full section padding above and below. */
.amenities.section { padding-block: var(--space-2xl); }
@media (min-width: 900px) {
  .amenities.section { padding-block: var(--space-3xl); }
}

.amenities__grid {
  display: grid;
  gap: var(--space-2xl);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 900px) {
  .amenities__grid { grid-template-columns: 7fr 5fr; gap: var(--space-3xl); }
}
.amenities h2 { margin-block: var(--space-sm) var(--space-lg); }
/* On the desktop grid the title fits on a single line; JS then tracks it out to
   span the column exactly (end to end with the list). nowrap keeps it to one
   line if the fitter hasn't run yet (no-JS / pre-paint). */
@media (min-width: 900px) {
  .amenities h2 { white-space: nowrap; }
}

.amenities__list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  border-block-start: var(--divider-w) solid var(--border-on-dark);
}
@media (min-width: 560px) {
  .amenities__list {
    grid-template-columns: repeat(2, 1fr);
    column-gap: var(--space-2xl);
  }
}
.amenities__list li {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding-block: var(--space-sm);
  border-block-end: var(--divider-w) solid var(--border-on-dark);
  font-size: var(--fs-body);
  line-height: 1.3;
}
.amenities__icon {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  color: var(--color-text-on-dark-alt); /* Sandstone — quiet, not an accent */
}

.amenities__media {
  border-radius: var(--radius);
  overflow: hidden;
  aspect-ratio: 4 / 5;
}
/* The <img> is wrapped in <picture>, which is globally height:auto — so inside
   this 4:5 box it collapses to the image's own height and overflow just clips
   the bottom, ignoring object-position. Force the wrapper to fill the box. */
.amenities__media picture { display: block; width: 100%; height: 100%; }
/* Portrait 2:3 in a 4:5 box: anchor to the foot of the frame so the image sits
   as high as it can, trimming the empty timber wall above rather than the
   banquette, wine and cheese board below. */
.amenities__media img { width: 100%; height: 100%; object-fit: cover; object-position: center bottom; }
.amenities__making {
  margin-block-start: var(--space-xl);
  color: var(--color-text-secondary);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  max-width: none; /* span the full column, end to end with the list above */
}

/* --- Producers strip -----------------------------------------------------
   Revision 2: producer names sit beside the wine photograph, not alone. */

.producers__grid {
  display: grid;
  gap: var(--space-2xl);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 900px) {
  .producers__grid { grid-template-columns: 7fr 5fr; gap: var(--space-3xl); }
}
.producers__head { max-width: 40rem; }
.producers__head h2 { margin-block: var(--space-sm) var(--space-md); }
.producers__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md) var(--space-lg);
  margin-block: var(--space-xl);
  font-size: clamp(1.125rem, 2vw, 1.5rem);
  font-weight: var(--fw-light);
}
.producers__list li { color: var(--color-text); }
.producers__addon {
  color: var(--color-text-secondary);
  font-size: var(--fs-small);
  margin-block-start: var(--space-lg);
}
.producers__media {
  border-radius: var(--radius);
  overflow: hidden;
  aspect-ratio: 4 / 5;
}
.producers__media img { width: 100%; height: 100%; object-fit: cover; }

/* --- Gift vouchers band -------------------------------------------------- */

.gift {
  position: relative;
  overflow: hidden;
  color: var(--color-text-on-dark);
}
.gift__media { position: absolute; inset: 0; z-index: 0; }
/* <picture> is globally height:auto, so in this full-bleed band it collapses to
   the image's own height and the banner just clips its top, ignoring
   object-position. Force the wrapper to fill the band. */
.gift__media picture { display: block; width: 100%; height: 100%; }
/* Portrait behind a wide banner: push the crop down the frame so the band lands
   on the salt bowl and towel rather than the dark top of the shot. */
.gift__media img { width: 100%; height: 100%; object-fit: cover; object-position: center 55%; }
.gift::after {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background-image: var(--scrim-band);
}
.gift .container { position: relative; z-index: 2; }
.gift h2 { color: var(--color-text-on-dark); margin-block: var(--space-sm) var(--space-md); }
.gift p { color: var(--color-text-on-dark-alt); }
.gift__cta { margin-block-start: var(--space-lg); }

/* --- Guides teaser ------------------------------------------------------- */

.guides__head { margin-block-end: var(--space-2xl); } /* left-aligned (Rev 2) */
/* Revision 2: no boxes. Plain text links with generous spacing, and a single
   rule below the whole group rather than a border around each card. */
.guides-grid {
  display: grid;
  gap: var(--space-xl) var(--space-2xl);
  grid-template-columns: 1fr;
  border-block-end: var(--divider-w) solid var(--border-on-light);
  padding-block-end: var(--space-2xl);
}
@media (min-width: 640px) { .guides-grid { grid-template-columns: repeat(2, 1fr); } }
.guide-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}
.guide-card__title {
  font-size: var(--fs-h3);
  font-weight: var(--fw-regular);
  color: var(--color-text-on-light);
  transition: color var(--dur-fast) var(--ease);
}
.guide-card:hover .guide-card__title,
.guide-card:focus-within .guide-card__title { color: var(--color-accent); }
.guide-card__cta { color: var(--color-text-on-light-2); font-size: var(--fs-small); }

/* --- Getting here + FAQ -------------------------------------------------- */

.getting {
  display: grid;
  gap: var(--space-2xl);
  grid-template-columns: 1fr;
}
@media (min-width: 900px) { .getting { grid-template-columns: 5fr 7fr; gap: var(--space-3xl); } }

.distances { display: grid; gap: var(--space-md); }
.distances h2 { margin-block-end: var(--space-sm); }
/* "Getting here" — the three distances read as a route: a copper hairline
   threads through three nodes, each stop pairing a tabular-figure travel time
   with its origin. Editorial, quiet, and on-theme for arrival. */
.route {
  list-style: none;
  margin: var(--space-lg) 0 0;
  padding: 0;
}
.route__stop {
  position: relative;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  min-height: 4.25rem;
  padding-block: var(--space-sm);
  padding-inline-start: calc(var(--space-lg) + 0.25rem);
  border-block-start: var(--divider-w) solid var(--border-on-light);
}
.route__stop:last-child { border-block-end: var(--divider-w) solid var(--border-on-light); }

/* Connecting line: each stop paints a full-height hairline on the rail; the
   first starts at its node and the last ends at its node, so the line runs
   cleanly node-to-node whatever the row height. */
.route__stop::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 4px;
  width: var(--divider-w);
  background: var(--c-copper);
  opacity: 0.4;
}
.route__stop:first-child::after { inset-block-start: 50%; }
.route__stop:last-child::after  { inset-block-end: 50%; }

/* Node */
.route__stop::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 50%;
  transform: translateY(-50%);
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--c-copper);
  box-shadow: 0 0 0 4px var(--color-band-light); /* ring masks the line behind */
  z-index: 1;
}

.route__time { display: flex; align-items: baseline; gap: 0.2em; }
.route__num {
  font-size: clamp(1.875rem, 4.5vw, 2.75rem);
  font-weight: var(--fw-light);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--color-text-on-light);
}
.route__unit {
  font-size: var(--fs-small);
  color: var(--color-text-on-light-2);
}
.route__place {
  text-align: end;
  font-size: 1.0625rem;
  color: var(--color-text-on-light);
  line-height: 1.3;
}
.route__from {
  display: block;
  font-size: 0.7rem;
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--color-text-on-light-2);
  margin-block-end: 0.15rem;
}

/* Address / place block */
.place {
  display: flex;
  gap: var(--space-sm);
  margin-block-start: var(--space-xl);
}
.place__pin {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  margin-block-start: 0.15rem;
  color: var(--c-copper);
}
.place__body { display: grid; gap: var(--space-2xs); justify-items: start; }
.place__addr {
  font-size: 1.0625rem;
  font-weight: var(--fw-medium);
  color: var(--color-text-on-light);
}
.place__desc {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  color: var(--color-text-on-light-2);
  max-width: 34ch;
}
.place .link-arrow { margin-block-start: var(--space-2xs); }

/* Staggered entrance for the route stops, layered on the section reveal.
   Guarded so it never hides content when motion is reduced or JS is absent. */
@media (prefers-reduced-motion: no-preference) {
  .js .distances.reveal .route__stop { opacity: 0; transform: translateY(10px); }
  .js .distances.reveal.is-visible .route__stop {
    opacity: 1;
    transform: none;
    transition: opacity var(--dur-mid) var(--ease-out),
                transform var(--dur-mid) var(--ease-out);
  }
  .js .distances.reveal.is-visible .route__stop:nth-child(1) { transition-delay: 0.08s; }
  .js .distances.reveal.is-visible .route__stop:nth-child(2) { transition-delay: 0.18s; }
  .js .distances.reveal.is-visible .route__stop:nth-child(3) { transition-delay: 0.28s; }
}

/* Accordion — Revision 2: heavy Copper dividers replaced with a soft hairline */
.faq { display: grid; gap: 0; margin-block-start: var(--space-xl); }
.faq__item { border-bottom: var(--divider-w) solid var(--border-on-light); }
.faq__item:first-child { border-top: var(--divider-w) solid var(--border-on-light); }
.faq__summary {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding-block: var(--space-md);
  text-align: left;
  font-size: 1.125rem;
  font-weight: var(--fw-regular);
  color: var(--color-text-on-light);
}
.faq__icon {
  flex-shrink: 0;
  width: 1rem; height: 1rem;
  position: relative;
}
.faq__icon::before,
.faq__icon::after {
  content: "";
  position: absolute;
  inset-block-start: 50%; inset-inline-start: 0;
  width: 100%; height: 2px;
  background-color: var(--color-accent);
  transition: transform var(--dur-fast) var(--ease);
}
.faq__icon::after { transform: rotate(90deg); }
.faq__summary[aria-expanded="true"] .faq__icon::after { transform: rotate(0); }
.faq__panel { overflow: hidden; }
/* Collapse only when JS is present; without JS every answer stays visible. */
.js .faq__panel {
  max-height: 0;
  transition: max-height var(--dur-fast) var(--ease);
}
.faq__panel-inner { padding-block-end: var(--space-md); color: var(--color-text-on-light-2); }
.faq__cta { margin-block-start: var(--space-lg); }

/* --- Closing CTA --------------------------------------------------------- */

.closing {
  position: relative;
  overflow: hidden;
  color: var(--color-text-on-dark);
  /* Centring comes from the inner .prose--center (a permitted centred block).
     This is the only centred section that survives site-wide. */
}
.closing__media { position: absolute; inset: 0; z-index: 0; }
/* <picture> is globally height:auto, so in this full-bleed band it collapses to
   the image's own height and the banner just clips its top. Force it to fill. */
.closing__media picture { display: block; width: 100%; height: 100%; }
/* Push the crop down the frame so the band shows more of the stone bath and its
   sunset reflection along the bottom, not just the sky up top. */
.closing__media img { width: 100%; height: 100%; object-fit: cover; object-position: center 70%; }
.closing::after {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background-image: var(--scrim-band);
}
.closing .container { position: relative; z-index: 2; }
.closing h2 { color: var(--color-text-on-dark); }
.closing__line { margin-block: var(--space-md); color: var(--color-text-on-dark-alt); }
.closing__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  justify-content: center;
  align-items: center;
}
.closing__phone {
  color: var(--color-text-on-dark);
  border-bottom: var(--divider-w) solid var(--color-accent);
  padding-bottom: 2px;
  font-weight: var(--fw-medium);
}
.closing__phone:hover,
.closing__phone:focus-visible { color: var(--color-accent); }

/* --- Footer -------------------------------------------------------------- */

.site-footer {
  /* The footer sits on the same Forest green used throughout the site, so it
     reads as one continuous ground with the dark sections above rather than
     switching to a separate warm anchor tone (was --c-earth). */
  background-color: var(--color-band-deep);
  color: var(--color-text-on-dark);
  padding-block: var(--space-3xl) var(--space-2xl);
}
.footer-grid {
  display: grid;
  gap: var(--space-xl);
  grid-template-columns: 1fr;
}
/* Narrow mobile: brand/description stays full width, then the three link
   lists share two columns (Stay / The valley side by side) to shorten the
   footer instead of stacking everything in one tall column. */
@media (max-width: 639px) {
  .footer-grid { grid-template-columns: repeat(2, 1fr); gap: var(--space-xl) var(--space-lg); }
  .footer-brand { grid-column: 1 / -1; }
}
@media (min-width: 640px) { .footer-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .footer-grid { grid-template-columns: 1.4fr 1fr 1fr 1.2fr; } }

.footer-col h3,
.footer-col__title {
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: var(--color-text-on-dark-alt);
  margin-block-end: var(--space-md);
}
.footer-col ul { display: grid; gap: var(--space-2xs); }
.footer-col a {
  font-size: var(--fs-small);
  color: var(--color-text-on-dark);
  transition: color var(--dur-fast) var(--ease);
}
.footer-col a:hover,
.footer-col a:focus-visible { color: var(--color-accent); }
.footer-brand { display: grid; gap: var(--space-sm); }
.footer-brand__mark { width: 180px; max-width: 70%; height: auto; }
.footer-brand p { color: var(--color-text-on-dark-alt); font-size: var(--fs-small); max-width: 44ch; }

/* Acknowledgement + photo credits share one row so neither leaves the right
   half of the footer empty. Stacks on narrow screens. */
.footer-meta {
  margin-block-start: var(--space-3xl);
  padding-block: var(--space-lg);
  border-top: var(--divider-w) solid var(--border-on-dark);
  border-bottom: var(--divider-w) solid var(--border-on-dark);
  display: grid;
  gap: var(--space-lg) var(--space-2xl);
  grid-template-columns: 1fr;
}
@media (min-width: 720px) {
  .footer-meta { grid-template-columns: 1.6fr 1fr; }
}
.footer-ack__label {
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--color-text-on-dark-alt);
  margin-block-end: var(--space-sm);
}
.footer-ack p,
.footer-credits p { color: var(--color-text-on-dark-alt); font-size: var(--fs-small); max-width: none; }

.footer-legal {
  margin-block-start: var(--space-lg);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-md);
  align-items: center;
  color: var(--color-text-on-dark-alt);
  font-size: var(--fs-small);
  font-weight: var(--fw-regular);
}
.footer-legal a { color: var(--color-text-on-dark-alt); }
.footer-legal a:hover,
.footer-legal a:focus-visible { color: var(--color-accent); }

/* Agency credit sits opposite the copyright, hard right on desktop.
   Wraps to its own line on narrow screens. */
.footer-legal__credit { margin-inline-start: auto; }
@media (max-width: 719px) { .footer-legal__credit { margin-inline-start: 0; } }

/* Keep the mobile bottom bar from covering the footer legal row */
@media (max-width: 899px) {
  .site-footer { padding-block-end: calc(var(--space-2xl) + 72px); }
}


/* --- "As seen in" press strip -------------------------------------------
   Sits flush on the Forest page beneath the reviews block: the light reviews
   band above gives it a clean edge. (The alternative, a Sandstone strip with
   Forest logos, blended into the reviews band above, see DECISIONS.md.)
   All fourteen marks render one uniform off-white: the SVGs via currentColor,
   the rasters as <img> recoloured off-white with a brightness/invert filter.
   (The original CSS mask was invisible in Chrome; see the raster note below and
   DECISIONS.md.) A centred wrap, last row centred, sizes each mark off the
   32/24px baseline times its opticalScale so every mark reads at one weight. */
.press { text-align: center; }
/* Cap the band height so it never opens a tall empty gap (Rev 4). */
.press.section { padding-block: 92px; }
@media (max-width: 899px) { .press.section { padding-block: 72px; } }
.press__eyebrow { margin-block-end: var(--space-xl); }
/* Height-normalised, centred wrap. Every mark is sized by height (baseline x
   opticalScale) and takes its own natural width, so wordmarks as wide as Hunter
   & Folk (12:1) and square roundels like Tailored Tasmania still read at one
   optical weight. A fixed equal-column grid can't hold that spread of aspect
   ratios, so the row count settles at roughly six across on desktop with the
   last row centred, which is the intended rhythm. */
.press-grid {
  --press-h: 32px;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;   /* centres each row, including the last partial one */
  align-items: center;
  gap: var(--space-lg) 3.5rem;
  max-width: 56rem;
  margin-inline: auto;
  color: var(--color-text-on-dark); /* off-white marks on the Forest strip */
}
.press-grid > li {
  display: flex;
  align-items: center;
  justify-content: center;
}
@media (max-width: 639px) {
  .press-grid { --press-h: 24px; gap: var(--space-md) var(--space-xl); }
}
.press-logo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: inherit;
  opacity: .62;
}
a.press-logo { transition: opacity var(--dur-fast) var(--ease); }
a.press-logo:hover,
a.press-logo:focus-visible { opacity: 1; }
.press-logo--svg svg { height: calc(var(--press-h) * var(--s)); width: auto; display: block; }
/* Rasters render as a plain <img>. The CSS-mask approach (currentColor + a
   masked PNG) proved unreliable in Chrome even with a single source and an
   explicit alpha mode, so per the brief we abandon it. The black-on-transparent
   PNGs are recoloured to off-white with a brightness/invert filter, which is
   universally supported; srcset carries @1x/@2x/@3x for retina. Sized by height
   (baseline x opticalScale) exactly like the SVGs so every mark reads at one
   optical weight. */
.press-logo--raster img {
  height: calc(var(--press-h) * var(--s));
  width: auto;
  display: block;
  filter: brightness(0) invert(1);
}
.press-logo--type {
  font-family: var(--font-primary);
  font-weight: var(--fw-medium);
  font-size: 18px;
  letter-spacing: 0.03em;
  color: inherit;
  white-space: nowrap;
}

