/* ==========================================================================
   core.css — Hunter Huon Valley
   GENERATED FILE. Do not edit.

   tokens.css + base.css + home.css, concatenated in that order by
   scripts/build-css.mjs so that every page makes one request instead of
   three. Edit the source files and run `npm run css`.
   ========================================================================== */

/* --- tokens.css ------------------------------------------------------------ */
/* ==========================================================================
   tokens.css — Hunter Huon Valley
   Design tokens ONLY. Every colour, space, size, radius, duration and
   breakpoint used anywhere on the site is defined here as a custom property.
   Seventeen more pages inherit this file. Nothing is hard-coded elsewhere.
   ========================================================================== */

:root {

  /* --- Colour -------------------------------------------------------------
     Warm, earthy, minimal. REVISION 4 (dark-dominant, corrected): the client
     asked for a darker background using Forest in Olive's place. So the page
     is Forest-dominant with off-white text on top (her "warm earthy tones with
     off-white text"). Roughly 60% Forest, 20% light linen relief bands,
     15% photographic, 5% Earth. This restores the Revision 2 dark-dominant
     structure and only substitutes Forest for Olive.
     Olive is RETIRED: it stays defined below but has zero references in any
     stylesheet. Copper is demoted to hovers, underlines and star icons only. */

  --c-base:       #F7F4EE; /* warm off-white, the ink + crisp cream cards        */
  --c-linen:      #ECE4D3; /* warm oat/linen, THE light section bands (as live) */
  --c-sandstone:  #D8D2C4; /* warm sandstone, secondary text + review highlight  */
  --c-sandstone-band: #D2CBBA; /* RETIRED. Rev 4's deeper band tone; the light   
                                  bands went back to linen. Zero references.     */
  --c-sage:       #A2A68D; /* background tint only, keep rare (5:1 on Forest)     */
  --c-olive:      #5E6347; /* RETIRED (Rev 4). Kept defined, zero references.     */
  --c-forest:     #2E3628; /* THE dominant page colour + dark bands + ink-on-light*/
  --c-forest-deep:#1B2018; /* pressed/hover state of a Forest fill. Added for the
                              Lodgify booking box, whose Book Now button needs a
                              darker shade of its own fill and cannot do the
                              site's tonal-shift-to-Sandstone hover.            */
  --c-earth:      #4A3322; /* accent only now: light-band button hover. No longer
                              the footer or the contact hero (2026-08-25).      */
  --c-oak:        #7A573A; /* texture, dividers only                             */
  --c-copper:     #B86F4A; /* accent only: hovers, underlines, small accents     */
  --c-gold:       #C6952E; /* warm harvest gold, review stars fill               */
  --c-gold-deep:  #9A6F1E; /* deeper gold, star edge, definition on light        */

  /* --- Semantic colour roles ----------------------------------------------
     REVISION 4 (dark-dominant): --color-page-bg resolves to Forest and
     --color-text to off-white. Every property name is preserved so nothing
     downstream breaks; only what they point at has changed. Contrast on
     Forest #2E3628: off-white 11.4:1, Sandstone 8.3:1 (softened to ~80% here),
     Copper 3.3:1 (never behind small text, hovers/underlines only).          */

  --color-page-bg:            var(--c-forest);    /* Forest, the dominant page */
  --color-band-alt:           var(--c-sandstone); /* legacy light band, tints  */
  --color-band-dark:          var(--c-forest);    /* dark bands (menu, bars)   */
  --color-text:               var(--c-base);      /* off-white on Forest, 11.4:1*/
  --color-text-secondary:     rgba(216, 210, 196, 0.8); /* Sandstone @ ~80%    */
  --color-text-on-dark:       var(--c-base);      /* off-white on Forest/photo */
  --color-text-on-dark-alt:   var(--c-sandstone); /* softer text on Forest     */
  --color-accent:             var(--c-copper);
  --color-accent-text:        var(--c-base);      /* off-white on Copper (rare)*/
  --color-divider:            var(--c-oak);
  --color-focus:              var(--c-copper);
  --color-star:               var(--c-gold);      /* review star fill          */
  --color-star-edge:          var(--c-gold-deep); /* review star hairline edge */

  /* Band + on-light roles (Revision 4) */
  --color-band-deep:          var(--c-forest);    /* Forest dark bands         */
  --color-band-light:         var(--c-linen);     /* warm oat light sections   */
  --color-band-light-alt:     var(--c-sandstone); /* the second light tone     */
  --color-text-on-light:      var(--c-forest);    /* Forest text on Sandstone  */
  --color-text-on-light-2:    rgba(46, 54, 40, 0.85); /* muted Forest secondary*/

  /* Review highlight (marker-pen effect): Sandstone behind Forest text */
  --color-highlight-bg:       var(--c-sandstone);
  --color-highlight-text:     var(--c-forest);

  /* Scrim used over hero / full-bleed imagery — kept a gradient, not a wash.
     Heavier at the base so off-white type pops. */
  --scrim-hero:   linear-gradient(to top, rgba(46, 54, 40, 0.88) 0%, rgba(46, 54, 40, 0.52) 45%, rgba(46, 54, 40, 0.22) 100%);
  --scrim-band:   linear-gradient(to bottom, rgba(46, 54, 40, 0.55), rgba(46, 54, 40, 0.55));
  /* Soft top-down gradient behind the transparent header over photography */
  --scrim-header: linear-gradient(to bottom, rgba(46, 54, 40, 0.55), transparent);
  /* Phone hero headline: a tight edge plus a wide soft glow, Forest-tinted */
  --shadow-hero-text: 0 1px 2px rgba(46, 54, 40, 0.35), 0 2px 24px rgba(46, 54, 40, 0.45);

  /* Translucent light used on top of Forest/Olive bands (base tint) */
  --overlay-on-dark: rgba(247, 244, 238, 0.08); /* --c-base @ 8%  */
  --border-on-dark:  rgba(247, 244, 238, 0.15); /* --c-base @ 15% */
  /* Soft hairline on light bands — a low-opacity Forest, so dividers read as a
     whisper rather than the old heavy Copper lines. */
  --border-on-light: rgba(46, 54, 40, 0.14);    /* --c-forest @ 14% */
  --ring-on-light:   rgba(46, 54, 40, 0.08);    /* --c-forest @ 8% — card inset */

  /* --- Typography ---------------------------------------------------------- */

  /* Type family (Rev 5) — locked 25 Aug 2026. Self-hosted, see fonts.css.
     ONE family sitewide: Montserrat, for headings, body, nav, buttons and
     labels alike. This supersedes the Rev 3 Fraunces (display) + Inter Tight
     (body) pairing, which is fully removed from the repo. Deliberately a
     single custom property so a second family can't drift back in. */
  --font-primary: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI",
                  Helvetica, Arial, sans-serif;

  /* 300 is reserved for pull-quotes and large stat numbers, where size covers
     for the weight; body stays 400 so off-white on Forest doesn't vibrate. */
  --fw-light:    300;
  --fw-regular:  400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;

  /* Rev 5 (§3 weight-contrast check): max stepped 5.5rem -> 5rem. Montserrat
     Bold 700 at 88px read heavier than the header wordmark it sits under; the
     weight is the point of matching the mark, so the size gave way, not the
     weight. Rate (7vw) unchanged. Reverse: restore 5.5rem.
     Floor also stepped 3rem -> 2.25rem: Montserrat is materially wider than
     Inter Tight, and at 48px "accommodation" (the longest word in the hero H1)
     overflowed its 335px column at 375px by ~65px. 40px measured as an exact
     335px fit, i.e. zero headroom, and still clipped under a different
     rasteriser; 36px leaves a real margin. Reverse: restore 3rem, but re-check
     the hero at 375px and 320px if you do. */
  --fs-h1:      clamp(2.25rem, 7vw, 5rem);
  --fs-h2:      clamp(2rem, 4vw, 3.25rem);
  --fs-h3:      clamp(1.25rem, 2vw, 1.5rem);
  --fs-body:    clamp(1.0625rem, 0.4vw + 1rem, 1.125rem);
  --fs-eyebrow: 0.6875rem;
  --fs-small:   0.875rem;
  --fs-stat:    clamp(2.5rem, 5vw, 3.75rem);

  --lh-h1:      1.08;
  --lh-h2:      1.15;
  --lh-h3:      1.3;
  --lh-body:    1.7;
  --lh-small:   1.6;

  --ls-h1:      -0.02em;
  --ls-h2:      -0.015em;
  /* 0.12em, not the Inter-era 0.15em — Montserrat's caps are wider and
     0.15em reads over-spaced at SemiBold 600. */
  --ls-eyebrow: 0.12em;
  --ls-label:   0.12em;

  --measure:    65ch; /* max line length for body copy */

  /* --- Spacing scale ------------------------------------------------------- */

  --space-3xs:  0.25rem;
  --space-2xs:  0.5rem;
  --space-xs:   0.75rem;
  --space-sm:   1rem;
  --space-md:   1.5rem;
  --space-lg:   2rem;
  --space-xl:   3rem;
  --space-2xl:  4rem;
  --space-3xl:  6rem;

  /* Section vertical padding — generous is the point */
  --section-py:        140px;
  --section-py-mobile: 80px;

  /* --- Layout -------------------------------------------------------------- */

  --content-max:  1200px;
  --gutter:       clamp(1.25rem, 5vw, 3rem);
  --header-h:     72px;

  /* --- Radius (never above 4px) ------------------------------------------- */

  --radius-sm: 2px;
  --radius:    4px;

  /* --- Borders / dividers -------------------------------------------------- */

  --divider-w: 1px;

  /* --- Motion -------------------------------------------------------------- */

  --dur-fast:    300ms;
  --dur-mid:     600ms;
  --dur-reveal:  700ms;
  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
  --ease:        ease-out;

  --reveal-shift: 20px;

  /* --- Elevation (no drop shadows on cards; used only for sticky header
         hairline separation via border, kept as token for consistency) ---- */
  --z-header:  1000;
  --z-mobile-menu: 1100;
  --z-bottom-bar: 900;

  /* --- Breakpoints (reference values; media queries can't read vars, but
         these document the canonical breakpoints for the whole site) ------ */
  --bp-lg: 1200px;
  --bp-md: 900px;
  --bp-sm: 640px;
}

/* Very narrow phones (older SE-class, 320px): even the 2.5rem H1 floor leaves
   "accommodation" wider than its column in Montserrat, which is materially
   wider than the Inter Tight it replaced. Stepped to 2rem below 360px only, so
   the common 375px case keeps the larger 40px setting. Reverse: delete this. */
@media (max-width: 359px) {
  :root { --fs-h1: 2rem; }
}

/* --- base.css ------------------------------------------------------------ */
/* ==========================================================================
   base.css — Hunter Huon Valley
   Reset, typography, layout primitives, utilities. No colours or sizes are
   hard-coded here; everything references tokens.css.
   ========================================================================== */

/* --- Reset --------------------------------------------------------------- */

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

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-h);
}

body {
  font-family: var(--font-primary);
  font-size: var(--fs-body);
  font-weight: var(--fw-regular);
  line-height: var(--lh-body);
  color: var(--color-text);
  background-color: var(--color-page-bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
}

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

button,
input,
select,
textarea { font: inherit; color: inherit; }

button { cursor: pointer; background: none; border: none; }

a { color: inherit; text-decoration: none; }

ul, ol { list-style: none; padding: 0; }

/* --- Typography ---------------------------------------------------------- */

/* Headings are Montserrat, sentence case, Medium 500 at every level.
   Bold 700 was tried first (to match the weight of the logo mark) and read too
   heavy against the fine, letter-spaced wordmark; at 500 the type turns airy and
   editorial, which is the look this site wants. Hierarchy is carried entirely by
   SIZE, not weight — the steps are wide (88 / 52 / 24px), so it reads clearly
   without a weight change, and H3 can never end up heavier than its own H2.
   Labels, nav, eyebrows and buttons keep SemiBold 600: they are small and
   uppercase, and need the extra weight to hold at 11-14px.
   All-caps is reserved for eyebrows/nav/buttons/labels only. */
h1, h2, h3 {
  font-family: var(--font-primary);
  font-weight: var(--fw-medium);
  color: var(--color-text);
  text-wrap: balance;
}

h1 {
  font-size: var(--fs-h1);
  line-height: var(--lh-h1);
  letter-spacing: var(--ls-h1);
}

h2 {
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
  letter-spacing: var(--ls-h2);
}

h3 {
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
}

p { max-width: var(--measure); }

strong { font-weight: var(--fw-semibold); }

/* We ship Montserrat roman only, so a UA italic on <em> renders as a faux
   oblique (a synthesised slant), which is exactly the fake-italic the type
   direction rules out. Emphasis carries on weight instead. Reverse: delete
   this rule and ship a Montserrat italic file. */
em { font-style: normal; font-weight: var(--fw-medium); }

/* --- Utilities ----------------------------------------------------------- */

.eyebrow {
  display: inline-block;
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--color-text-secondary);
}

.small { font-size: var(--fs-small); line-height: var(--lh-small); }

.meta { color: var(--color-text-secondary); }

/* Layout primitives */

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

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

@media (min-width: 900px) {
  .section { padding-block: var(--section-py); }
}

/* Section band treatments (Revision 4, dark-dominant). Forest is the page
   default, so `.band--olive` (the dominant band, its name kept for markup
   stability though it now paints Forest not Olive) and `.band--forest` inherit
   off-white text and need no override. Light linen bands flip the text,
   headings and eyebrows to Forest. Reused across the sibling pages. */
.band--olive {
  background-color: var(--color-page-bg);
  color: var(--color-text-on-dark);
}
.band--forest {
  background-color: var(--color-band-deep);
  color: var(--color-text-on-dark);
}
.band--light {
  background-color: var(--color-band-light);
  color: var(--color-text-on-light);
}
.band--light-alt {
  background-color: var(--color-band-light-alt);
  color: var(--color-text-on-light);
}
.band--light h1, .band--light h2, .band--light h3,
.band--light-alt h1, .band--light-alt h2, .band--light-alt h3 {
  color: var(--color-text-on-light);
}
.band--light .eyebrow,
.band--light-alt .eyebrow { color: var(--color-text-on-light-2); }

/* Centred, measure-capped text block */
.prose {
  max-width: var(--measure);
  margin-inline: auto;
}
.prose > * + * { margin-top: var(--space-md); }
.prose--center { text-align: center; }

/* Full-bleed helper — breaks an element out of a centred container */
.full-bleed {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
}

/* Buttons ---------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  padding: var(--space-xs) var(--space-md);
  font-size: var(--fs-small);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  border-radius: var(--radius);
  transition: background-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}

/* Primary button.
   Revision 2: Copper on Olive is only 1.6:1, so the primary button is now an
   off-white fill with Forest text (11.4:1) — it sits on the dark Olive/Forest
   bands and over photography. On LIGHT bands it flips to a Forest fill with
   off-white text automatically (see the variant below).
   To bring copper buttons back, this is the one place: set background-color to
   var(--color-accent) and color to var(--color-accent-text). */
.btn--primary {
  background-color: var(--c-base);
  color: var(--c-forest);
}
/* Hover is a tonal shift to Sandstone, keeping Forest text (11:1). Copper is
   NOT used as a button fill: off-white on Copper is only ~3.9:1 and fails
   behind the 11px uppercase label. Copper stays on inline links/underlines. */
.btn--primary:hover,
.btn--primary:focus-visible {
  background-color: var(--c-sandstone);
  color: var(--c-forest);
}

/* Primary button variant for light sections */
.band--light .btn--primary,
.band--light-alt .btn--primary {
  background-color: var(--c-forest);
  color: var(--c-base);
}
.band--light .btn--primary:hover,
.band--light .btn--primary:focus-visible,
.band--light-alt .btn--primary:hover,
.band--light-alt .btn--primary:focus-visible {
  background-color: var(--c-earth);
  color: var(--c-base);
}

/* Ghost button.
   Revision 2: takes its colour from context via currentColor, so it is visible
   over the dark hero (off-white) and on light bands (Forest) alike, and always
   carries a 1px border. Copper appears only on hover. */
.btn--ghost {
  background-color: transparent;
  color: currentColor;
  border: var(--divider-w) solid currentColor;
}
.btn--ghost:hover,
.btn--ghost:focus-visible {
  color: var(--color-accent);
  border-color: var(--color-accent);
}

/* Text / ghost inline link with arrow */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  letter-spacing: 0.02em;
  color: var(--color-text);
  border-bottom: var(--divider-w) solid transparent;
  padding-bottom: 2px;
  transition: color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.band--light .link-arrow,
.band--light-alt .link-arrow { color: var(--color-text-on-light); }
.link-arrow:hover,
.link-arrow:focus-visible {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}

/* Inline text link */
.text-link {
  color: var(--color-text);
  border-bottom: var(--divider-w) solid var(--color-accent);
  transition: color var(--dur-fast) var(--ease);
}
.band--light .text-link,
.band--light-alt .text-link { color: var(--color-text-on-light); }
.text-link:hover,
.text-link:focus-visible { color: var(--color-accent); }

/* --- Accessibility ------------------------------------------------------- */

.skip-link {
  position: absolute;
  left: var(--space-sm);
  top: -100px;
  z-index: var(--z-header);
  padding: var(--space-2xs) var(--space-sm);
  background-color: var(--color-band-dark);
  color: var(--color-text-on-dark);
  border-radius: var(--radius);
  transition: top var(--dur-fast) var(--ease);
}
.skip-link:focus { top: var(--space-sm); }

:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

/* --- Scroll reveal ------------------------------------------------------
   Hiding is gated behind the `.js` flag (set on <html> before paint). With
   JavaScript disabled there is no `.js` class, so `.reveal` has no effect and
   all content is fully visible. */

.js .reveal {
  opacity: 0;
  transform: translateY(var(--reveal-shift));
  transition: opacity var(--dur-reveal) var(--ease-out),
              transform var(--dur-reveal) var(--ease-out);
  will-change: opacity, transform;
}
.js .reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* --- Reduced motion ------------------------------------------------------
   No !important (site rule). These rules sit last in the cascade and match
   the same or higher specificity as the animated rules above, so they win. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .js .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .btn,
  .link-arrow,
  .text-link,
  .skip-link,
  .site-header,
  .site-header__inner,
  .cabin-card__media img,
  .nav__dropdown,
  .mobile-menu { transition: none; }

  .cabin-card:hover .cabin-card__media img { transform: none; }
}

/* --- home.css ------------------------------------------------------------ */
/* ==========================================================================
   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 width to the wordmark (151 x 32 since Rev 73) so
     the two ends of the header are the same width and the bar reads
     symmetric. The 38px height is the button's own, not the wordmark's. */
  .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.
   32px, not the 38px it was until Rev 73: the old asset baked ~8.5% of empty
   canvas above and below the letterforms, so 38px of canvas drew 31.5px of
   ink. hunter-logo-white-600.png is cropped hard to the ink, so the clear
   space is now this rule's job. 32px reproduces the old drawn height, and the
   box lands at 151x32, which keeps the 152px the header CTA is matched to. */
.brand__mark {
  height: 32px;
  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; }
/* The toggle is a <button>, and base.css gives buttons `font: inherit`, so
   until 7 Sep 2026 it inherited body weight and normal tracking while its six
   sibling .nav__link items were semibold with 0.02em. "Stay" read visibly
   lighter than every other item in the bar. It now carries the same two
   declarations as .nav__link so the whole nav is one weight. */
.nav__toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3xs);
  font-size: var(--fs-small);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.02em;
  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;
  /* Top padding trimmed from --space-xl and the close button lifted out of
     the flow (31 Aug 2026) so the list starts at the top of the panel. The
     nine items plus the Stay submenu and the Book Now button overflowed a
     ~700px phone viewport, and the overflow was small enough to read as a
     broken layout rather than a scroll. Reverse: restore --space-xl /
     --space-2xl here and drop the absolute positioning below. */
  padding: var(--space-md) var(--gutter) var(--space-lg);
  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 {
  /* Out of the flow: in it, the close button cost a whole 40px row above a
     list that already did not fit. It sits at the right edge, clear of the
     short first item. */
  position: absolute;
  inset-block-start: var(--space-md);
  inset-inline-end: var(--gutter);
  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-xs);
  margin-block-start: 0;
}
.mobile-menu__list a,
.mobile-menu__label {
  font-size: 1.375rem;
  font-weight: var(--fw-light);
}
/* "Stay" in the mobile menu is a group label, not a link: /stay/ was removed
   9 Sep 2026 and the three cabins below it are the destinations. The desktop
   nav already used a <button> toggle here, so this brings the two into line. */
.mobile-menu__label {
  display: block;
  color: var(--color-text-secondary);
}
.mobile-menu__list a:hover,
.mobile-menu__list a:focus-visible { color: var(--color-accent); }
.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;
  }
}
/* Phones and tablets: a bigger, bolder headline (client request, 14 Sep
   2026). The base --fs-h1 bottoms out at 36px on every phone, so the line
   read small against the photo. Here it scales with the viewport instead:
   41px at 390, 45px at 430, 56px on tablets. The limit is the longest word.
   In semibold "accommodation" is 8.2em wide, so a 36px floor ran it 16px
   past the 280px column at 320; the floor is 2rem and 10.5vw sets 33.6px
   there. Above ~343px it is larger than before everywhere. Semibold 600 is
   real (the variable font runs 300-700). The soft shadow holds the letters
   off the sun flare behind them. Desktop is untouched, see the note above
   on why it has no bump. */
@media (max-width: 899px) {
  /* Shorter hero on phones and tablets (client request, 14 Sep 2026): 90svh
     left a tall band of dark floor under the bath before the booking search.
     Still a min-height, so the hero grows rather than crops if the copy
     ever needs more room. Desktop keeps 90svh. */
  .hero { min-height: 72svh; }
  .hero__content h1 {
    font-size: clamp(2rem, 10.5vw, 3.5rem);
    font-weight: var(--fw-semibold);
    line-height: 1.04;
    text-shadow: var(--shadow-hero-text);
  }
}

/* --- 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 this rule. */
#lodgify-search-bar, #lodgify-search-bar * {
  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;
}
/* The <img> is wrapped in <picture>, which is globally height:auto, so the
   img's height:100% resolved against nothing: it drew at its own 2:3 height
   inside this 4:5 box and overflow clipped the bottom sixth, so every card
   showed the top of its photo. Filling the box lets object-fit do its job and
   centres the crop. Same fix as `.inset-split__media picture` (Rev 75). */
.cabin-card__media picture { display: block; width: 100%; height: 100%; }
.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);
}

.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);
}

/* 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);
}

/* "Swipe to see more" under the rating. Only the phone and tablet row is
   swiped (see the max-width: 899px block below), so it is hidden by default
   and switched on there. The arrow is a thin line with a head, drawn in the
   text colour. */
.reviews__hint { display: none; }
.reviews__hint svg {
  flex: none;
  width: 2.5rem;
  height: 0.75rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* 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; }
}

/* Phones and tablets: a swipeable row, not the auto-scroll. The looping
   track is 16 cards twice over, about 5,800px wide at 390, and animated
   under a mask it becomes a composited layer iOS Safari will not draw: the
   section kept its height and showed nothing (reported 14 Sep 2026). Here
   nothing moves on its own, the mask and the duplicate set go, and the row
   runs edge to edge with each card snapping to the gutter. */
@media (max-width: 899px) {
  .review-marquee {
    margin-inline: calc(-1 * var(--gutter));
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--gutter);
    -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: max-content;
  }
  .review-set {
    gap: var(--space-md);
    padding-inline: var(--gutter);
  }
  .review-set[aria-hidden="true"] { display: none; }
  .review-card { scroll-snap-align: start; }
  .reviews__hint {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-xs);
    margin: var(--space-md) 0 0;
    font-size: var(--fs-small);
    color: var(--color-text-on-light-2);
  }
}

/* --- 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); }
/* Answers are usually one paragraph and stay a <p>. The three client-written
   answers added 1 Sep 2026 run to two or three, so the class also has to work
   on a wrapping <div>: same idiom as .cabin-about, a gap between siblings
   rather than margins on the paragraphs. The accordion measures scrollHeight,
   so a taller panel needs no JS change. */
.faq__panel-inner > * + * { margin-block-start: var(--space-md); }
.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); }
/* Holds one child now: the Book Now button. The phone link that used to sit
   beside it came out on 7 Sep 2026, so .closing__phone is gone with it. The
   flex centring stays because it is what centres the lone button, and it
   still handles a second child if one is ever added back. */
.closing__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  justify-content: center;
  align-items: center;
}

/* An optional pointer sitting above the CTA, off it by one step. Moved
   here from about.css on 1 Sep 2026 when /eat-drink/ became the second page to
   use it: every other .closing__* rule already lives in this file, so a shared
   part of a shared component was the one piece living in a page stylesheet.
   /about/ ships it `hidden` and is unaffected; /eat-drink/ shows it. */
.closing__aside { margin-block-end: var(--space-lg); }

/* --- 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; }

/* Brand Tasmania "Proud Partner" mark.
   Its own full-width row between the credits and the legal line. Brand
   Tasmania sets a 250px minimum width for this primary lockup and asks for
   clear space around it of at least the cap height of the "T" in TASMANIAN
   (about 7.8px at this size). A row of its own with --space-lg (32px) above
   and below clears that several times over on every side, and means the
   badge never has to shrink to share a line with anything.

   The artwork ships as supplied: no filter, background, border, radius or
   shadow, and height:auto so it is never stretched. The hover dip is on the
   link, not the image, so nothing about the mark itself is animated. */
.footer-mark {
  margin-block-start: var(--space-lg);
  /* The badge and the entity line share this row, which keeps the footer one
     row shorter than giving the entity its own. space-between puts the entity
     hard right, opposite the badge; the --space-lg gap is several times the
     clear space Brand Tasmania asks for, and wrapping means the two never
     collide at narrow widths. align-items:center reads better than baseline
     here because the badge is an image, not text. */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
}
.tasmanian-mark {
  display: inline-block;
  transition: opacity var(--dur-fast) var(--ease);
}
.tasmanian-mark:hover,
.tasmanian-mark:focus-visible { opacity: 0.85; }
.tasmanian-mark img {
  display: block;
  /* 250px is the Brand Tasmania minimum for the primary lockup. The footer
     container is at least 280px wide even at a 320px viewport, so this size
     holds all the way down and never falls to the 180px mobile floor. */
  width: 250px;
  height: auto;
}

.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); }

/* Registered entity and ABN. It shares the .footer-mark row rather than taking
   one of its own, hard right opposite the Brand Tasmania badge, which keeps
   the footer a row shorter. It is not inside .footer-legal: that is a wrapping
   flex row with the agency credit pushed hard right by margin-inline-start:
   auto, so anything added to it would move that credit.

   Off-white (--color-text-on-dark) held back by opacity so the disclosure is
   legible but recedes: at 0.55 over Forest it still clears 4.5:1, which the
   smaller --fs-eyebrow size needs. Deliberately duller than the Sandstone
   --color-text-on-dark-alt used by the rest of the footer, because this is
   fine print and nothing above it should have to compete. */
.footer-entity {
  max-width: 62ch;
  color: var(--color-text-on-dark);
  opacity: 0.55;
  font-size: var(--fs-eyebrow);
  line-height: var(--lh-small);
  text-align: end;
}
/* Stacked under the badge on narrow screens, where a right-aligned ragged-left
   block of fine print is harder to read than a plain left-aligned one. */
@media (max-width: 719px) {
  .footer-entity { text-align: start; }
}

/* 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 sixteen 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 rows settle at 4 / 5 / 4 / 3 across on desktop with the last row
   centred, which is the intended rhythm. The order the marks are written in is
   what decides those breaks: see the manifest and DECISIONS.md Rev 60. */
.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;
}
