/* ============================================================
   On The Bay B&B
   Palette: deep garden green, chalk, sand, rose, sea
   Type: Fraunces (display) + Karla (text)
   ============================================================ */

:root{
  /* colour */
  --ink:        #1C3A31;
  --ink-soft:   #2F5145;
  --ink-mute:   #5B7568;
  /* Warm linen. Was #EFF2EA, a cool grey-green, changed Sept 2026 at the
     owner's request. Two reasons it reads better: every other accent on
     the site is warm (--rose gold, --sand, the --rose-tint band), so the
     cool grey-green was the one cold note; and #EFF2EA sat almost
     exactly level with --rose-tint in lightness (ΔL 0.016), so the
     gallery/contact seam barely registered. This separates from both
     neighbours — ΔL 0.10 from --paper, 0.02 from --rose-tint — while
     keeping 10.5:1 contrast for --ink text.
     NOTE this token is not only a background: it is also the light TEXT
     colour on the dark footer and .band-deep, the fill of the .chips
     pills and the .cb-card contact cards, and the .nav-dropdown
     hover/current background. Check all five when changing it. */
  --chalk:      #F1ECE1;
  --paper:      #F8F9F4;
  --sand:       #E7DCCA;
  --rose:       #F9CB5F;
  --rose-deep:  #F2AD0D;
  --rose-tint:  #FBEED0;
  --sea:        #4F8F8B;
  --line:       rgba(28,58,49,.15);
  --line-light: rgba(255,255,255,.22);

  /* type */
  --serif:  "Fraunces", "Iowan Old Style", Georgia, serif;
  --sans:   "Karla", "Helvetica Neue", Arial, sans-serif;
  --script: "Sacramento", cursive;

  /* scale (1.25) */
  --t--1: .8125rem;
  --t-0:  1.0625rem;
  --t-1:  1.3125rem;
  --t-2:  1.625rem;
  --t-3:  2.0625rem;
  --t-4:  2.5rem;

  /* rhythm */
  --gut: clamp(20px, 5vw, 56px);
  --band: clamp(64px, 9vw, 124px);
  --maxw: 1220px;
  --r: 3px;
  /* Height of the fixed header. Drives BOTH .head-inner's min-height and
     html's scroll-padding-top, which must agree exactly: the header is
     fixed, so an anchor jump has to stop that far down or the section
     lands either behind the header or below it. These used to be three
     independent hand-set numbers (76px header, 88px desktop
     scroll-padding, 74px mobile) and every anchor link was visibly off —
     12px of the previous section showing through on desktop, 2px of the
     target tucked under the header on mobile. The header is the same
     height at every width, so there is no breakpoint override any more.
     If the header's height ever changes, change it HERE. */
  --head-h: 76px;
}

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

/* No extra breathing room is added on top of --head-h on purpose: every
   section is a .band with its own var(--band) of top padding, so landing
   the section's edge flush under the header still leaves its content
   comfortably clear. */
html{ scroll-behavior:smooth; scroll-padding-top:var(--head-h); -webkit-text-size-adjust:100%; }
@media (prefers-reduced-motion:reduce){ html{ scroll-behavior:auto; } }

body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font:400 var(--t-0)/1.68 var(--sans);
  -webkit-font-smoothing:antialiased;
}

/* height:auto is the required companion to the width/height attributes now
   on every <img> in the markup (added Sept 2026 to stop layout shift — see
   CLAUDE.md "Image dimensions"). Without it, max-width:100% shrinks the
   width on a narrow container while the height attribute stays at the
   photo's full intrinsic value, stretching it. Every rule below that sets
   an explicit height (.hero-img, .bookbox-head-img, .around-photo-img) is
   a class selector and so still wins over this. */
img{ max-width:100%; height:auto; display:block; }

a{ color:inherit; }

.skip{
  position:absolute; left:-9999px; top:0; z-index:200;
  background:var(--ink); color:#fff; padding:12px 18px;
}
.skip:focus{ left:12px; top:12px; }

:focus-visible{ outline:2.5px solid var(--rose); outline-offset:3px; border-radius:2px; }

.shell{ width:min(100% - (var(--gut) * 2), var(--maxw)); margin-inline:auto; }

/* ---------- type ---------- */
.h-sec{
  font-family:var(--serif);
  font-weight:400;
  font-size:clamp(1.9rem, 4.2vw, 3rem);
  line-height:1.08;
  letter-spacing:-.015em;
  margin:0 0 .5em;
  font-variation-settings:"opsz" 96;
}
.h-min{
  font-family:var(--serif);
  font-weight:500;
  font-size:var(--t-1);
  line-height:1.25;
  margin:0 0 .55em;
  font-variation-settings:"opsz" 24;
}
.lede{ font-size:var(--t-1); line-height:1.55; color:var(--ink-soft); max-width:60ch; }
p{ margin:0 0 1.05em; max-width:66ch; }
.fine{ font-size:var(--t--1); color:var(--ink-mute); }

/* ---------- buttons ---------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center;
  gap:.5em; padding:.92em 1.5em;
  font:600 var(--t--1)/1 var(--sans);
  letter-spacing:.02em;
  border:1px solid transparent; border-radius:var(--r);
  text-decoration:none; cursor:pointer;
  transition:background-color .18s ease, color .18s ease, border-color .18s ease;
}
.btn-solid{ background:var(--rose); color:#000; }
.btn-solid:hover{ background:var(--rose-deep); }
.btn-ghost{ background:transparent; color:#fff; border-color:rgba(255,255,255,.55); }
.btn-ghost:hover{ background:rgba(255,255,255,.14); border-color:#fff; }
.btn-line{ background:transparent; color:var(--ink); border-color:var(--line); }
.btn-line:hover{ border-color:var(--ink); background:rgba(28,58,49,.05); }
.btn-sm{ padding:.72em 1.1em; }

/* ============================================================
   HEADER
   ============================================================ */
.site-head{
  position:fixed; inset:0 0 auto 0; z-index:90;
  color:#fff;
  transition:background-color .3s ease, box-shadow .3s ease, color .3s ease;
}
.site-head::after{
  content:""; position:absolute; inset:0; z-index:-1;
  background:linear-gradient(rgba(16,34,28,.62), rgba(16,34,28,0));
  transition:opacity .3s ease;
}
.site-head.stuck{ background:var(--paper); color:var(--ink); box-shadow:0 1px 0 var(--line); }
.site-head.stuck::after{ opacity:0; }

.head-inner{
  display:flex; align-items:center; gap:clamp(16px,3vw,40px);
  min-height:var(--head-h); padding-block:12px;
}

.brand{ display:flex; align-items:center; gap:12px; text-decoration:none; margin-right:auto; }
.brand-mark{ width:34px; height:34px; flex:none; }
.brand-words{ display:flex; flex-direction:column; line-height:1.15; }
.brand-name{ font-family:var(--serif); font-weight:500; font-size:1.25rem; letter-spacing:-.01em; white-space:nowrap; }
.brand-sub{ font-size:.7rem; letter-spacing:.09em; opacity:.8; }

.nav{ display:flex; gap:clamp(14px,2vw,28px); }
.nav a{
  text-decoration:none; font-size:var(--t--1); font-weight:500;
  padding:6px 0; position:relative; white-space:nowrap;
}
.nav a::after{
  content:""; position:absolute; left:0; right:100%; bottom:0; height:1.5px;
  background:currentColor; transition:right .22s ease;
}
.nav a:hover::after{ right:0; }

/* "Rooms" nav item — a real link (still goes straight to the rooms
   listing page on click) that also reveals a hover dropdown of all six
   rooms, so a visitor can jump straight to one without landing on the
   listing page first. Ported in spirit from the reference site's own
   nav__trigger/nav__dropdown pattern; hover-only by design, so it keeps
   the site's no-extra-JS approach — see the mobile override below for how
   touch devices get the same list without relying on hover. */
.nav-item{ position:relative; }
.nav-trigger{ display:inline-flex; align-items:center; gap:5px; }
.nav-caret{ width:9px; height:9px; opacity:.7; transition:transform .2s ease; }
.nav-item:hover .nav-caret,
.nav-item:focus-within .nav-caret{ transform:rotate(180deg); }

/* invisible bridge over the gap between the trigger and the dropdown
   below it — without this, moving the pointer straight down from "Rooms"
   toward the panel crosses a dead zone that's over neither element, so
   :hover drops for a moment and the panel starts fading out mid-transit.
   This sits exactly in that gap (same height as the dropdown's
   margin-top) and, as generated content of .nav-item, keeps counting as
   part of it the whole way down. */
.nav-item::after{ content:""; position:absolute; top:100%; left:0; right:0; height:14px; }

.nav-dropdown{
  position:absolute; top:100%; left:0; margin-top:14px; z-index:95;
  min-width:230px; padding:8px; display:flex; flex-direction:column;
  background:var(--paper); color:var(--ink); border:1px solid var(--line);
  border-radius:10px; box-shadow:0 26px 46px -26px rgba(28,58,49,.4);
  opacity:0; visibility:hidden; transform:translateY(6px);
  transition:opacity .2s ease, transform .2s ease, visibility .2s;
}
.nav-item:hover .nav-dropdown,
.nav-item:focus-within .nav-dropdown{
  opacity:1; visibility:visible; transform:translateY(0);
}
.nav-dropdown a{
  padding:.7em .8em; border-radius:6px; font-size:var(--t--1); font-weight:500;
  color:var(--ink); white-space:nowrap;
}
.nav-dropdown a::after{ display:none; }
/* background-only feedback — no accent-colour text here, so it doesn't
   read as "gone yellow" against --rose's current warm-gold value */
.nav-dropdown a:hover,
.nav-dropdown a:focus-visible{ background:var(--chalk); }
.nav-dropdown a[aria-current="page"]{ background:var(--chalk); font-weight:600; }

.head-actions{ display:flex; align-items:center; gap:14px; }

/* explicit color, not just inherited from .site-head — form controls
   (button/input/select) don't inherit `color` from ancestors the way a
   plain `<a>` or `<span>` does, so without this the bars fell back to the
   browser's own default button text colour (dark) even while the header
   itself was still in its transparent, white-text state over the hero
   photo, making the icon unreadably dark against a dark photo. Only
   needs the explicit light value here — the dark .stuck state below
   overrides it back to --ink once the header goes solid. */
.burger{ display:none; width:40px; height:36px; background:none; border:0; cursor:pointer; padding:8px 6px; color:#fff; }
.burger span{ display:block; height:1.6px; background:currentColor; margin:5px 0; transition:transform .25s ease, opacity .2s ease; }
.site-head.stuck .burger{ color:var(--ink); }
.burger[aria-expanded="true"] span:nth-child(1){ transform:translateY(6.6px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2){ opacity:0; }
.burger[aria-expanded="true"] span:nth-child(3){ transform:translateY(-6.6px) rotate(-45deg); }

/* ============================================================
   HERO
   ============================================================ */
.hero{ position:relative; isolation:isolate; color:#fff; }
.hero-img{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; z-index:-2;
}
/* compact-single's banner is its own landscape crop, banner.webp (2:1,
   2880x1440), NOT its photo #1 — the owner's photo is portrait, and `cover`
   on this short wide box threw away ~70% of it and upscaled a 1086px file.
   The banner is cut from the 48MP original instead (see CLAUDE.md).

   Only this one room needs the class. On a screen wider than 2:1 the whole
   width shows and only the vertical position matters, which the crop
   itself already sets. On anything narrower (tablets, phones) `cover`
   trims the SIDES, and the bed sits left of this photo's centre — centred,
   a phone slices the headboard in half and leaves the cushion on the
   edge. 30% keeps the cushion, lamp and nightstand in frame there.

   Photo-specific, so RE-CHECK it if banner.webp is ever re-cropped: render
   the hero at ~390 and ~768 px wide and look. */
.hero-img--left{ object-position:30% center; }
.hero-scrim{
  position:absolute; inset:0; z-index:-1;
  background:
    linear-gradient(180deg, rgba(16,34,28,.55) 0%, rgba(16,34,28,.28) 42%, rgba(16,34,28,.86) 100%),
    linear-gradient(95deg, rgba(16,34,28,.62) 0%, rgba(16,34,28,.05) 62%);
}
.hero-inner{ padding-top:clamp(140px,20vh,220px); padding-bottom:clamp(56px,9vh,110px); }

.hero-place{
  font-size:var(--t--1); letter-spacing:.13em; margin:0 0 1.1em;
  color:rgba(255,255,255,.85);
}
/* small uppercase label + short rule, sitting above the title on the
   room-page hero — the same "label + line" shape as `.eyebrow` further
   down the page, just white-on-photo and with the rule drawn in instead
   of relying on a border, since there's no element below to border. */
.hero-eyebrow{
  display:flex; align-items:center; gap:14px;
  font:700 12px/1 var(--sans); letter-spacing:.16em; text-transform:uppercase;
  color:rgba(255,255,255,.86); margin:0 0 1em;
}
.hero-eyebrow::after{
  content:""; flex:1 1 auto; max-width:70px; height:1px;
  background:rgba(255,255,255,.55);
}
.hero-title{
  font-family:var(--serif); font-weight:300;
  font-size:clamp(2.5rem, 7.2vw, 5.2rem);
  line-height:1.02; letter-spacing:-.025em;
  margin:0 0 .42em; max-width:16ch;
  font-variation-settings:"opsz" 144;
  text-wrap:balance;
}
/* the closing line ("hear it.") picked out in italic + a warm cream, not
   plain white like the rest of the title — a small typographic accent on
   the title's own punchline */
.hero-title-accent{ font-style:italic; color:var(--rose-tint); }
.hero-lede{
  font-size:clamp(1.0625rem,1.7vw,1.3125rem); line-height:1.6;
  max-width:46ch; color:rgba(255,255,255,.92); margin-bottom:2em;
}
.hero-cta{ display:flex; flex-wrap:wrap; gap:16px; }
/* bigger than the sitewide .btn default and a touch more rounded — the
   plain 13px/3px-radius button reads as undersized and slightly harsh
   next to the large hero title/lede above it. Scoped to the hero only;
   the header "Book Now" button and every other .btn on the site keeps
   the flatter, smaller sitewide default on purpose (see CLAUDE.md on the
   .room cards for why that flat language shouldn't get "fixed" globally). */
.hero-cta .btn{ padding:1em 1.75em; font-size:.9375rem; border-radius:7px; }

/* short banner variant — room detail pages. Same hero/hero-img/hero-scrim
   markup as the homepage hero, just a lot less tall and with the title
   pinned to the bottom instead of a full title+lede+CTA stack. */
.hero--room{ min-height:min(58svh,500px); }
.hero--room .hero-inner{
  min-height:min(58svh,500px);
  display:flex; flex-direction:column; justify-content:flex-end;
  padding-top:140px; padding-bottom:clamp(36px,6vh,60px);
}
.hero--room .hero-title{ font-size:clamp(2.1rem,5.6vw,3.6rem); margin:0 0 .3em; max-width:20ch; }
/* a short single-line subtitle, not the long-form paragraph .hero-lede is
   sized for on the homepage — smaller, no bottom margin (title/eyebrow
   above already carry the spacing), plain sans weight for contrast
   against the serif title. */
.hero--room .hero-lede{
  font:600 clamp(1rem,1.6vw,1.1875rem)/1.5 var(--sans);
  max-width:42ch; margin:0; color:rgba(255,255,255,.92);
}
/* the base .hero-scrim above is tuned for the homepage's full-height,
   green-toned garden hero — its percentage stops reach full darkness
   gradually over a ~94vh box. Reused as-is on this much shorter banner,
   those same stops compress into a fast ramp that reads as a heavy,
   green-tinted wash over the whole photo rather than a gentle darkening
   at the edges (which is what actually showed up: room photos looking
   dull/off-colour, not just "a bit darker"). This override swaps it for
   a plain neutral (no green) black gradient, lighter overall, that only
   really darkens the bottom strip the title sits on. */
.hero--room .hero-scrim{
  background:linear-gradient(180deg, rgba(0,0,0,.1) 0%, rgba(0,0,0,.04) 32%, rgba(0,0,0,.6) 100%);
}

/* fact ribbon */
.ribbon{
  position:relative;
  display:grid; grid-template-columns:repeat(4,1fr);
  margin:0; padding:0; list-style:none;
  border-top:1px solid var(--line-light);
  background:rgba(16,34,28,.42);
  backdrop-filter:blur(3px);
}
.ribbon li{
  padding:22px clamp(14px,2.4vw,32px);
  border-left:1px solid var(--line-light);
  display:flex; flex-direction:column; gap:3px;
}
.ribbon li:first-child{ border-left:0; padding-left:max(var(--gut), calc((100vw - var(--maxw)) / 2)); }
.ribbon li:last-child{ padding-right:max(var(--gut), calc((100vw - var(--maxw)) / 2)); }
.ribbon strong{ font-family:var(--serif); font-weight:500; font-size:var(--t-1); }
.ribbon span{ font-size:var(--t--1); color:rgba(255,255,255,.78); }

/* entrance — one orchestrated moment on load */
.js-rise{ opacity:0; transform:translateY(14px); }
.ready .js-rise{
  opacity:1; transform:none;
  transition:opacity .7s ease var(--d,0ms), transform .7s cubic-bezier(.2,.7,.3,1) var(--d,0ms);
}
@media (prefers-reduced-motion:reduce){
  .js-rise{ opacity:1; transform:none; }
  .ready .js-rise{ transition:none; }
}

/* ============================================================
   BANDS
   ============================================================ */
/* Top padding is deliberately smaller than the bottom (was equal, both
   var(--band)) — the gap above a section's eyebrow reads better tighter
   than the gap a section leaves below its own content before the next
   band starts. Matches the value #around already used for the same
   reason (see its own comment below); that section's own override is
   now redundant with this default but is left in place since its
   min-height reservation math quotes this value verbatim and needs an
   explicit, easy-to-find source for it. */
.band{ padding-top:clamp(44px,5.2vw,72px); padding-bottom:var(--band); }
.band-chalk{ background:var(--chalk); }
.band-paper{ background:var(--paper); }
.band-sand{ background:var(--sand); }
.band-deep{ background:var(--ink); color:var(--chalk); }
.band-rose{ background:var(--rose-tint); }

.sec-head{ max-width:64ch; margin-bottom:clamp(36px,5vw,64px); }
.sec-head .lede{ margin-bottom:0; }
.sec-head-light .lede{ color:rgba(239,242,234,.8); }

/* ---------- welcome split ---------- */
.split{ display:grid; grid-template-columns:1.15fr .85fr; gap:clamp(32px,6vw,84px); align-items:start; }
.split-text p{ color:var(--ink-soft); }
.split-fig{ margin:0; position:sticky; top:110px; }
.split-fig img{ width:100%; aspect-ratio:3/4; object-fit:cover; border-radius:var(--r); }
.split-fig figcaption{
  margin-top:14px; font-size:var(--t--1); color:var(--ink-mute);
  border-left:2px solid var(--rose); padding-left:12px; max-width:34ch;
}

/* ---- Welcome (#stay) text column ---- */
/* Rebuilt Sept 2026 to an owner-supplied mockup: heading, a wave flourish,
   an uppercase subtitle, the body copy, a 4-up icon fact row, and a script
   sign-off. The mockup also carried a solid "Book Your Stay" button on the
   sign-off row; the owner asked for it to be dropped, so the sign-off is
   the section's last element and starts at the gutter. */

/* One ripple under the heading, same motif as .bookbox-head-waves on the
   room pages. The stroke is rgba rather than var(--line) on purpose: at
   .15 alpha a 2px stroke all but disappears, and this is meant to read as
   a drawn flourish, not as the hairline rules that .eyebrow-rule and
   .welcome-signoff draw with --line further down this same column. */
.welcome-wave{
  display:block; width:96px; height:auto; margin:.5em 0 1.45em;
  fill:none; stroke:rgba(28,58,49,.32); stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round;
}

/* Deliberately NOT .eyebrow, even though it looks like one. That class is
   the small label ABOVE a heading and is reused on all six room cards and
   the chips-group labels (see CLAUDE.md § Section eyebrows) — giving it a
   second, larger role below a heading would mean any future change to
   .eyebrow silently hit those too. */
.welcome-sub{
  margin:0 0 1.5em;
  font:700 .78rem/1.5 var(--sans); letter-spacing:.2em; text-transform:uppercase;
  color:var(--ink-soft);
}

/* The mockup breaks the heading over two lines ("Welcome to / On The Bay"),
   which is most of what gives the wave flourish below it the right
   proportion. The break is made by the markup — one block <span> per line,
   nowrap — rather than by capping the width.

   It used to be `max-width:8.5ch`, a measured window between "Welcome to"
   (7.41ch) and "Welcome to On" (9.69ch). That only holds while the font
   is the one it was measured in: on a real phone it broke as "Welcome /
   to On The / Bay", because ch is the width of a "0" and the ratio of "0"
   to letters shifts with the font actually used (fallback while Fraunces
   loads, different optical-size handling, Safari). A width window that
   narrow is a bet on font metrics; two explicit lines are not. Each line
   is ~175px at the smallest size against a ~320px column, so nowrap has
   ~2x headroom before anything could overflow. Keep the wording in the
   spans in step with what this comment says if it is ever changed. */
.split-text .h-sec{
  /* Scaled up from the sitewide .h-sec clamp (1.9/4.2vw/3rem) so the
     heading's lines come out the same width as the .welcome-sub line
     below it, which the owner asked for. At the top of the clamp
     "On The Bay" measures ~253px against the subtitle's 252px.

     Note the two can only match at desktop: .welcome-sub is a fixed rem
     size with fixed letter-spacing, so it is 252px at EVERY viewport,
     while the heading scales. At 390px the heading lines are ~153px and
     the subtitle is still 252px. Matching there too would mean either a
     ~57px heading on a 350px column or a subtitle too small to read.

     The two-line break comes from the markup, not from a width — see
     the note above. */
  font-size:clamp(2.15rem, 4.95vw, 3.55rem);
}
.split-text .h-sec span{ display:block; white-space:nowrap; }

/* Four feature callouts, replacing the <dl class="facts"> that was here.
   minmax(0,1fr) rather than a bare 1fr for the reason documented on
   .roomlayout and .cb-cols: a grid item's default min-width is auto, so a
   bare 1fr lets a long word push the track — and the page — wider than the
   viewport instead of wrapping. */
.welcome-facts{
  list-style:none; margin:2.5em 0 0; padding:0;
  display:grid; grid-template-columns:repeat(4,minmax(0,1fr));
}
.welcome-facts li{
  display:flex; flex-direction:column; align-items:center; text-align:center;
  padding:0 12px; border-left:1px solid var(--line);
}
.welcome-facts li:first-child{ border-left:0; padding-left:0; }
/* Explicit margins rather than a flex `gap`: the icon needs more air below
   it than the two text lines need between them, and one gap can't do both. */
.welcome-fact-icon{
  display:grid; place-items:center; width:44px; height:44px; margin-bottom:13px;
  /* the same circle badge as .dist-icon, .bookbox-icon and .cb-fact-icon */
  border-radius:50%; background:rgba(28,58,49,.08); color:var(--ink);
}
.welcome-fact-icon svg{ width:21px; height:21px; }
.welcome-facts b{
  margin-bottom:5px;
  font:700 .72rem/1.2 var(--sans); letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink);
}
.welcome-facts small{ font-size:var(--t--1); line-height:1.35; color:var(--ink-mute); }

/* Two per row once four would be ~85px each. This query MUST stay below the
   :first-child rule above — the two selectors are equally specific, so at
   equal specificity the later one wins no matter which sits in a media
   query. That exact trap already bit .cb-gk once; see CLAUDE.md. */
@media (max-width:620px){
  .welcome-facts{ grid-template-columns:repeat(2,minmax(0,1fr)); row-gap:28px; }
  /* With two columns the border has to clear on the first cell of EVERY
     row, not just the very first — nth-child(odd) is the left column. */
  .welcome-facts li:nth-child(odd){ border-left:0; padding-left:0; }
}

/* Same construction as .dist-more (script line, rule trailing off right) and
   .cb-signoff (same, but centred and rule-flanked on both sides). Three
   near-identical rules now; kept separate rather than folded into a shared
   utility because each is tuned to its own section's size and spacing.
   max-width:none is load-bearing — it's a <p>, and the base `p` rule caps
   every paragraph at 66ch, which would stop the rule short of the column. */
.welcome-signoff{
  display:flex; align-items:center; gap:clamp(14px,2.2vw,22px);
  margin:2.6em 0 0; max-width:none;
  font-family:var(--script); font-size:clamp(1.3rem,2vw,1.6rem);
  color:var(--ink-soft);
}
.welcome-signoff::after{ content:""; flex:1 1 auto; height:1px; background:var(--line); }

.facts{ margin:2.2em 0 0; display:grid; gap:0; border-top:1px solid var(--line); }
.facts > div{
  display:flex; justify-content:space-between; gap:20px;
  padding:.78em 0; border-bottom:1px solid var(--line);
}
.facts dt{ font-size:var(--t--1); color:var(--ink-mute); }
.facts dd{ margin:0; font-weight:500; text-align:right; }
.facts dd a{ text-decoration:none; border-bottom:1px solid var(--line); }
.facts dd a:hover{ border-color:var(--rose); color:var(--rose); }
.facts-tight{ margin-top:1.4em; }

/* ---------- rooms ---------- */
/* cards float with their own border/shadow, rather than the flat hairline-
   tile grid this used before — a deliberate departure from the site's
   otherwise sharp-cornered, shadowless language, asked for specifically to
   match a reference room-card layout (relaxedcityliving.co.za/rooms) */
.rooms{ display:grid; grid-template-columns:repeat(3,1fr); gap:clamp(16px,2.2vw,28px); }
/* Sept 2026 redesign, modelled on a mockup the owner supplied: a badge +
   working photo carousel over the image and a "Room type" eyebrow. The
   card briefly stopped being a single `<a>` over this (a `<button>` isn't
   valid content inside an `<a>`), but the owner wanted click-anywhere back
   — so the carousel buttons' click handlers stop the click from bubbling
   up to the card's own `<a>` (`e.stopPropagation()` in script.js, the same
   trick `.lb-prev`/`.lb-next` already use against the lightbox `<dialog>`),
   which lets a `<button>` live inside an `<a>` and still work as a
   button — a real HTML conformance wart (interactive content nested in a
   hyperlink), kept deliberately for the click-anywhere UX it buys back. */
.room{
  background:var(--paper); border:1px solid var(--line); border-radius:14px; overflow:hidden;
  display:flex; flex-direction:column; position:relative;
  text-decoration:none; color:inherit;
  transition:transform .3s ease, box-shadow .3s ease;
}
.room:hover{ transform:translateY(-5px); box-shadow:0 26px 44px -28px rgba(28,58,49,.4); }
.room-img{ overflow:hidden; position:relative; }
.room-img img{ width:100%; aspect-ratio:4/3; object-fit:cover; transition:transform .6s ease; }
.room:hover .room-img img{ transform:scale(1.045); }

/* small pill top-left of the photo, alternating light/dark across the
   row (set per-card in the markup) purely for visual rhythm — not tied
   to any particular room's meaning */
.room-badge{
  position:absolute; top:14px; left:14px; z-index:1;
  display:inline-flex; align-items:center; gap:.5em;
  padding:.5em .95em; border-radius:100px;
  font:700 11px/1 var(--sans); letter-spacing:.04em; text-transform:uppercase;
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
  pointer-events:none;
}
.room-badge svg{ width:14px; height:14px; flex:none; }
.room-badge--light{ background:rgba(251,238,208,.94); color:var(--ink); }
.room-badge--dark{ background:rgba(16,34,28,.8); color:#fff; }

/* photo carousel — cycles that room's own photo set (script.js reads
   data-slug/-count/-ext off .room-img and rewrites the <img src> plus
   this counter on click; no page reload, no lightbox). Sits where the
   old static "9 photos" badge used to. */
.room-carousel{
  position:absolute; right:12px; bottom:12px; z-index:1;
  display:flex; align-items:center; gap:6px;
}
.room-carousel-btn{
  display:flex; align-items:center; justify-content:center;
  width:26px; height:26px; border-radius:50%; border:0; padding:0; cursor:pointer;
  background:rgba(16,34,28,.72); color:#fff;
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
  transition:background-color .2s ease;
}
.room-carousel-btn:hover{ background:rgba(16,34,28,.92); }
.room-carousel-btn svg{ width:12px; height:12px; }
.room-carousel-count{
  padding:.32em .7em; border-radius:100px;
  background:rgba(16,34,28,.72); color:#fff;
  font:600 11px/1 var(--sans); letter-spacing:.03em;
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
}

.room-body{ padding:clamp(20px,2.4vw,30px); display:flex; flex-direction:column; flex:1; position:relative; }
/* tighter eyebrow-to-title gap and a slightly larger title than
   .eyebrow/h3 default elsewhere — matches an owner-supplied reference
   screenshot of this exact spot on the card. Weight stayed at the sitewide
   h3 default (500) — a bolder 600/700 was tried first and was too heavy
   next to the reference, size/spacing were the actual gap. */
.room-body .eyebrow{ margin-bottom:.5em; }
.room-body h3{ font-family:var(--serif); font-weight:500; font-size:1.75rem; margin:0 0 .4em; line-height:1.15; }
.room-body > p{ color:var(--ink-soft); font-size:var(--t--1); line-height:1.62; position:relative; }

/* spec list — a vertical icon+text stack, used both bare (room detail
   page intro) and inside a .room-tag row (cards, paired with "View room") */
.spec{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:.5em; }
.spec li{ font-size:var(--t--1); color:var(--ink-mute); display:flex; align-items:center; gap:.55em; }
.spec svg{ width:15px; height:15px; flex:none; opacity:.72; }

.room-tag{
  margin-top:auto; border-top:1px solid var(--line); padding-top:.9em;
  display:flex; align-items:flex-end; justify-content:space-between; gap:1.2em; flex-wrap:wrap;
  position:relative;
}
.room-tag .spec{ flex:none; }

/* not a link of its own — the whole .room card is one — just styled like
   one, since the card is the click target */
.room-view{
  display:inline-flex; align-items:center; gap:.6em; flex:none;
  font:600 var(--t--1)/1.4 var(--sans); color:var(--ink-soft);
  transition:gap .22s ease, color .22s ease;
}
.room:hover .room-view{ gap:.85em; color:var(--ink); }
/* small circle button carrying the arrow, in place of a bare "→" —
   compact and inline with the "View room" text rather than the earlier
   redesign's version of this (a line stretching across the row to a much
   bigger 38px button); this is just the label plus a small icon */
.room-view-arrow{
  display:flex; align-items:center; justify-content:center; flex:none;
  width:30px; height:30px; border-radius:50%;
  background:var(--ink); color:#fff;
  transition:background-color .2s ease, transform .2s ease;
}
.room-view-arrow svg{ width:14px; height:14px; }
.room:hover .room-view-arrow{ background:var(--rose-deep); transform:translateX(3px); }

/* faint wave doodle low in the card body, echoing the same ripple motif
   as .bookbox-head-waves elsewhere — pure decoration, sits behind the
   text (z-index) and never intercepts clicks */
.room-body::after{
  content:""; position:absolute; right:-6px; bottom:-4px; z-index:0;
  width:96px; height:60px; pointer-events:none;
  opacity:.05;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 78 44'%3E%3Cg fill='none' stroke='%231C3A31' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M2 8 Q12 0 22 8 T42 8 T62 8'/%3E%3Cpath d='M8 22 Q18 14 28 22 T48 22 T68 22'/%3E%3Cpath d='M14 36 Q24 28 34 36 T54 36 T74 36'/%3E%3C/g%3E%3C/svg%3E");
  background-repeat:no-repeat; background-size:contain;
}
.room-body > *{ position:relative; z-index:1; }

/* ---------- room detail page ---------- */
/* the rooms LISTING page (rooms/index.html) still opens straight into its
   first band with no tall .hero to absorb the fixed header, so it still
   needs a flat top-padding to clear the ~100px fixed header plus a little
   breathing room. Individual room pages no longer need this — they now
   open with their own .hero--room banner (see above), so .room-top just
   takes the normal .band padding like any other section. */
.page-top{ padding-top:140px; }
/* the hero banner right above already gives this section a strong visual
   break (the photo edge + its shadow), so it doesn't need the full flat
   .band top padding a page-opening section has to fight — left at the
   .band default this was ~64-124px of dead air before the breadcrumb
   chip even started. Only trims the top; the bottom padding (separating
   this section from "Other rooms" below) is untouched. */
.hero--room + .room-top{ padding-top:clamp(28px,4vw,48px); }
/* rounded "chip" bar rather than plain inline text — a small circular
   home-icon badge (paper-on-chalk, echoing the .bookbox-icon circles)
   followed by the trail; the current page is a plain non-link span,
   set bolder/darker than the Home/Rooms links so it reads as "you are
   here" rather than another clickable step. */
.crumb{
  display:inline-flex; align-items:center; gap:.6em;
  margin:0 0 1.6em; padding:.4em 1.1em .4em .4em;
  border-radius:100px; background:var(--chalk);
  font-size:var(--t--1);
}
.crumb-icon{
  display:inline-flex; align-items:center; justify-content:center;
  width:30px; height:30px; border-radius:50%; flex:none;
  background:var(--paper); color:var(--ink-soft);
}
.crumb-icon svg{ width:14px; height:14px; }
.crumb a{ font-weight:600; color:var(--ink-mute); text-decoration:none; }
.crumb a:hover{ color:var(--rose); }
.crumb-current{ font-weight:700; color:var(--ink); }

/* small uppercase section label, used above the description/photos on a
   room page and above the "Rooms" section elsewhere — ported from the
   reference site's own `.eyebrow` treatment */
.eyebrow{
  display:block; margin:0 0 .9em;
  font:700 .72rem/1 var(--sans); letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-mute);
}
/* Section eyebrow with a short rule trailing the label — started life as
   .around-eyebrow on "What's around us" and is now on every section
   heading on the homepage.

   Opt-in via this extra class rather than restyling every .eyebrow,
   because .eyebrow is deliberately also used for SMALLER labels that
   should stay plain: "Room type" on each room card, "About the room" on
   the room detail pages, and the .chips-group-label headings. Adding
   the rule to those would put a trailing line inside every card.

   --line is a translucent ink (rgba(28,58,49,.15)), so the rule reads
   correctly on paper, chalk and rose-tint bands alike without needing a
   per-band variant. It would need one on a dark band — nothing uses
   .band-deep any more, but worth knowing if that comes back. */
.eyebrow-rule{ display:flex; align-items:center; gap:12px; }
.eyebrow-rule::after{ content:""; flex:1 1 auto; max-width:56px; height:1px; background:var(--line); }

/* two-column room-detail layout: a sticky booking box on the left,
   description + gallery on the right — modelled on
   relaxedcityliving.co.za's room pages, mirrored so the box that actually
   drives a booking is the first thing read, not an afterthought at the
   end of the scroll */
.roomlayout{
  display:grid; grid-template-columns:340px minmax(0,1fr);
  gap:clamp(28px,5vw,56px); align-items:start;
}
.roomlayout-main p{ color:var(--ink-soft); }

/* Room "About" section. Every claim in the prose and the feature lists is
   either already stated elsewhere on the site (spec, "In every room",
   breakfast price) or visible in that room's own photos — nothing is
   inferred beyond what a guest could check against the gallery below. */
.room-about-title{
  font-family:var(--serif); font-weight:400; color:var(--ink);
  font-size:clamp(1.6rem,2.6vw,var(--t-3)); line-height:1.15; letter-spacing:-.01em;
  margin:.35em 0 .55em;
}
.room-feat{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr)); gap:12px;
  margin:2em 0 1.5em;
}
.room-feat-group{
  display:grid; grid-template-columns:46px minmax(0,1fr); gap:14px; align-items:start;
  background:rgba(241,236,225,.45); border:1px solid rgba(28,58,49,.08);
  border-radius:14px; padding:15px 18px 16px 15px;
}
/* same translucent-ink circle as .bookbox-icon / .dist-icon, just larger */
.room-feat-icon{
  display:grid; place-items:center; width:46px; height:46px; border-radius:50%;
  background:rgba(28,58,49,.08); color:var(--ink);
}
.room-feat-icon svg{ width:22px; height:22px; }
.room-feat-h{
  font:700 12px/1 var(--sans); letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink); margin:.3em 0 .75em;
}
.room-feat ul{ list-style:none; margin:0; padding:0; }
.room-feat li{
  position:relative; padding-left:1.6em; color:var(--ink-soft);
  font-size:.9375rem; line-height:1.4;
}
.room-feat li + li{ margin-top:.35em; }
/* a drawn tick rather than an icon per line: one shape, and it stays
   crisp at this size */
.room-feat li::before{
  content:""; position:absolute; left:.25em; top:.25em;
  width:.36em; height:.7em; border:solid var(--sea); border-width:0 2px 2px 0;
  transform:rotate(45deg);
}
@media (max-width:480px){
  .room-feat-group{ grid-template-columns:40px minmax(0,1fr); gap:12px; padding:14px 16px 15px 14px; }
  .room-feat-icon{ width:40px; height:40px; }
  .room-feat-icon svg{ width:19px; height:19px; }
  .room-feat-h{ margin-top:.15em; }
}
.roomlayout-main .room-about-note{ font-size:var(--t--1); color:var(--ink-mute); }
.roomlayout-aside{ position:sticky; top:116px; }

.bookbox{
  background:var(--paper); border:1px solid var(--line); border-radius:24px;
  box-shadow:0 30px 54px -32px rgba(28,58,49,.4);
  overflow:hidden;
}

/* photo header panel: icon + title + "plan your stay" eyebrow over a real
   wave photo, a faint ripple doodle in the corner, and a wave seam into
   the body below instead of a hard edge. The wave seam isn't CSS — it's
   baked into images/bookbox-wave.webp's own alpha channel (owner-supplied,
   pre-cut to that shape), so `.bookbox-head-img` just needs to sit behind
   everything and let the card's own --paper background show through where
   the photo is transparent. */
.bookbox-head{
  position:relative; overflow:hidden;
  /* locked to the source photo's own ratio (bookbox-wave.webp is
     900x301) — this used to have no explicit height at all, just
     padding + content, which left `object-fit:cover` to crop the photo
     by however much the box's own aspect ratio (width varies a LOT:
     ~340px on the fixed-width desktop aside vs. the full page width once
     .roomlayout collapses to one column under 900px, while the height
     stayed pinned to content) happened to differ from the photo's own.
     At the widths in between — just past that collapse, where the aside
     is suddenly ~700-800px wide but the box was still only ~105px tall —
     the crop zoomed in far enough that the wave line rode up through the
     "Plan your stay" subtitle, washing it out to near-invisible. Matching
     the box's ratio to the photo's means `cover` never has anything to
     crop, so the wave sits at the same fraction of the box at every
     width. min-height is just a floor so a very narrow phone can't
     squeeze it shorter than the icon+heading content needs. */
  aspect-ratio:900/301; min-height:100px;
  padding:1.7rem 1.7rem 2rem;
  /* var(--paper), not a dark fallback — the photo's own alpha cuts the
     wave shape, and what that cutout reveals is this element's own
     background (the .bookbox-body sitting below is a separate box, not
     behind it), so this has to match the body for the two to read as one
     continuous card rather than a dark strip between photo and body */
  background:var(--paper); color:#fff;
}
.bookbox-head-img{
  position:absolute; inset:0;
  width:100%; height:100%; object-fit:cover; object-position:center bottom;
}
/* only darkens the top portion behind the icon/heading — confined well
   clear of the wave cutout lower down, so it can never leave a residual
   tint over the paper that shows through there */
.bookbox-head-scrim{
  position:absolute; top:0; left:0; right:0; height:58%;
  background:linear-gradient(180deg, rgba(10,30,35,.5) 0%, rgba(10,30,35,0) 100%);
}
.bookbox-head-top{ position:relative; display:flex; align-items:flex-start; gap:.8em; }
.bookbox-head-icon{ width:25px; height:25px; flex:none; margin-top:.2em; opacity:.95; }
.bookbox-head h3{
  font-family:var(--serif); font-weight:700; font-size:1.5rem; line-height:1.15;
  margin:0 0 .32em; letter-spacing:-.01em;
  text-shadow:0 2px 10px rgba(10,30,35,.3);
}
.bookbox-head-sub{
  margin:0; font:700 .68rem/1 var(--sans); letter-spacing:.16em; text-transform:uppercase;
  color:rgba(255,255,255,.8);
}
/* three ripple lines, echoing the water below */
.bookbox-head-waves{ position:absolute; right:14px; bottom:34px; width:78px; height:44px; z-index:1; pointer-events:none; }
.bookbox-head-waves path{ fill:none; stroke:rgba(255,255,255,.55); stroke-width:2; stroke-linecap:round; }

/* condensed (Sept 2026): the box used to end with a second "Enquire about
   this room" outline button plus a rule-flanked WhatsApp line below the
   facts — removed at the owner's request to shorten the card, since the
   floating .wa-float button already covers WhatsApp sitewide and the
   Nightsbridge button is the one action that actually matters here. What's
   below is tightened accordingly (smaller icon circles, tighter row/section
   gaps, no bottom padding held for a footnote that no longer exists). */
.bookbox-body{ padding:1.5rem 1.7rem 1.6rem; }

.bookbox-facts{ margin:0 0 1.3rem; display:grid; gap:.85em; }
.bookbox-facts .row{ display:flex; align-items:center; justify-content:space-between; gap:1em; }
.bookbox-facts dt{ display:flex; align-items:center; gap:.75em; color:var(--ink-mute); font-size:var(--t--1); font-weight:500; }
.bookbox-icon{
  display:grid; place-items:center; flex:none; width:34px; height:34px;
  border-radius:50%; background:rgba(28,58,49,.08); color:var(--ink);
}
.bookbox-icon svg{ width:16px; height:16px; }
/* Values are serif at weight 500, matching .cb-card-value in #contact
   rather than the bold sans they used to be: at 700 the sans read as app
   UI sitting next to the muted sans labels, and serif is what the rest of
   the site reaches for when the value is the thing worth looking at.

   text-wrap:balance is the substantive fix here. "2 singles, or king +
   single" (twin) is the only value long enough to wrap in the 340px
   sidebar, and right-aligned it stranded "single" alone on the second
   line, which read as a mistake. Balance splits it evenly instead.
   line-height has to come down with it — the inherited body line-height
   left a two-line value looking like two separate facts. */
.bookbox-facts dd{
  margin:0; text-align:right; color:var(--ink);
  font-family:var(--serif); font-weight:500; font-size:var(--t-0);
  line-height:1.3; text-wrap:balance;
}
/* a light rule ahead of the check-in row, separating "what the room is"
   facts from "when you can have it" facts */
.bookbox-facts .row-stay{ padding-top:.85em; border-top:1px solid var(--line); }

.bookbox-btn{
  display:flex; align-items:center; justify-content:center; gap:.45em;
  width:100%; padding:1em .9rem; border-radius:100px;
  font:700 .9rem/1.2 var(--sans); text-decoration:none;
}
.bookbox-btn svg{ width:16px; height:16px; flex:none; }
.bookbox-btn-solid{ background:var(--rose); color:var(--ink); transition:background-color .2s ease; }
.bookbox-btn-solid:hover{ background:var(--rose-deep); }

.room-more{ display:flex; flex-wrap:wrap; gap:10px 14px; }
.room-more-link{
  padding:.68em 1.2em; border:1px solid var(--line); border-radius:100px;
  font-size:var(--t--1); font-weight:600; color:var(--ink-soft); text-decoration:none;
  transition:border-color .2s ease, color .2s ease;
}
.room-more-link:hover{ border-color:var(--rose); color:var(--rose); }

/* ---------- rooms listing page ---------- */
.guide{ max-width:68ch; }
.cta-band{ display:flex; align-items:center; justify-content:space-between; gap:clamp(24px,4vw,48px); flex-wrap:wrap; }
.cta-band .lede{ margin-bottom:0; }

/* ---------- amenities ---------- */
.amen{ margin-top:clamp(44px,6vw,76px); }
.amen-list{
  list-style:none; margin:0 0 1.6em; padding:0;
  display:grid; grid-template-columns:repeat(4,1fr); gap:14px 28px;
}
.amen-list li{ display:flex; align-items:center; gap:11px; font-size:var(--t--1); color:var(--ink-soft); }
.amen-list svg{
  width:22px; height:22px; flex:none;
  fill:none; stroke:var(--sea); stroke-width:1.4; stroke-linecap:round; stroke-linejoin:round;
}
.amen-note{ font-size:var(--t--1); color:var(--ink-mute); border-left:2px solid var(--sea); padding-left:14px; max-width:52ch; }

/* ---------- around ---------- */
/* Redesigned Sept 2026 to match an owner-supplied mockup — light --paper
   band (was a dark --ink one; .band-deep/.sec-head-light stay defined in
   case a future section wants a dark band again, but neither is used
   here any more), an eyebrow + wavy-clipped photo panel above the
   existing two-column facts/chips grid. */
/* This override is now redundant with .band's own default top padding
   (both are this same clamp — see "BANDS" above) but is kept explicit
   rather than deleted: the min-height reservation below quotes this
   exact value verbatim, and that comment needs something concrete to
   point at rather than an inherited default. Originally this was
   .around's own exception — the photo panel is flush with the very top
   of the band (see below), so the site's old full `--band` top padding
   left the text stranded a long way down the photo — until the smaller
   value became the sitewide default for every section's eyebrow gap.
   The bottom keeps the standard --band. */
.around{
  position:relative; padding-top:clamp(44px,5.2vw,72px);
  /* The gap between the "Close by" and "Worth the drive" columns. It's a
     variable because the lede above them is width-matched to the "Close
     by" column, and that match is computed from this value — see
     .around-top .sec-head's max-width. Change it here only. */
  --around-gap:clamp(32px,6vw,80px);
}
/* Smaller than it was, bringing .around-grid up with it. */
.around-top{ margin-bottom:clamp(10px,1.2vw,18px); }
.around-top .sec-head{
  margin-bottom:0; display:flex; flex-direction:column; justify-content:center;
  /* The photo starts at the section's top edge, above where this column
     starts, so what has to be reserved here is only the part of the
     photo's height that hangs below .around's own padding-top — i.e. at
     least (photo height - that padding), so .around-grid below clears
     the wave's deepest point. The wave bottoms out at the very bottom
     of the photo's box (it runs off the right edge as the photo's
     bottom edge, rather than tapering away to the left), so the FULL
     height has to be cleared, not just part of it.

     This restates the photo's own height clamp and the section's own
     padding-top clamp verbatim and subtracts them, rather than being a
     third hand-tuned clamp approximating the difference. That is
     deliberate: the hand-tuned version silently under-reserved the
     moment the photo's height changed, and the photo grew straight
     through "Worth the drive" below it. Written this way the reservation
     tracks both automatically. The +8px is just air.
     KEEP THE TWO CLAMPS BELOW IDENTICAL to .around-photo's height and
     .around's padding-top. */
  min-height:calc(clamp(170px,16.5vw,360px) - clamp(44px,5.2vw,72px) + 8px);
  /* Width-matched to the "Close by" column below it, and DERIVED from
     .around-grid's own track sizing rather than eyeballed: that grid is
     `.9fr 1.1fr` with --around-gap between, so its left column is
     0.9/2.0 = 45% of what's left after the gap. If those tracks ever
     change, change this 0.45 to match — they are one decision in two
     places, which is the cost of the lede not being a grid item itself.

     This also has to keep the lede clear of .around-photo, which is
     absolutely positioned and which nothing here accounts for
     automatically (.lede's own 60ch default is wide enough to run clean
     underneath it). The column width happens to clear it comfortably at
     every width checked — 950/1100/1280/1440/1600/1920/2560 — but that
     is a verified coincidence, not something the formula guarantees.
     Re-measure if the photo's `left`, height or clip path changes. */
  max-width:calc((100% - var(--around-gap)) * .45);
}
/* A little smaller than the sitewide .lede (--t-1, 1.3125rem). Off the
   type scale on purpose: --t-0 (1.0625rem) is the next step down and
   drops it to plain body size, which loses the lede's role as an intro.
   This sits between the two. */
.around-top .lede{ font-size:1.1875rem; }
/* (the eyebrow rule that used to live here as .around-eyebrow is now the
   shared .eyebrow-rule, up with .eyebrow) */

/* The photo panel bleeds to the viewport's right edge and is flush with
   the top of the band. It's a sibling of .shell rather than a grid
   column inside it (see index.html), for two reasons: it has to sit
   above .shell's own top padding, and it has to escape .shell's width
   cap to reach the viewport edge.

   `top:0` puts it level with the top of the band, and is the reason
   .around's padding-top is halved above — an absolutely positioned
   element's `top` ignores its container's padding entirely, so the
   photo starts at the colour boundary while the text below still gets
   normal padding.

   `left` is the only non-obvious one. A plain percentage of the section
   would keep sliding right forever on wide screens while .shell stays
   capped at --maxw and centred, so the text column's breathing room
   would *shrink* as the window grew (at 3000px it'd be down to ~310px
   from ~490px at 1440px). The max() pins the photo's left edge to 40%
   of .shell's own content box once --maxw kicks in — `(100% - --maxw)/2`
   is .shell's left offset, plus 40% of its width — so the gap between
   the text and the photo is constant on any screen wider than about
   1330px. Below that .shell is gutter-bound rather than --maxw-bound,
   the first term underestimates, and the plain 40% wins. */
.around-photo{
  position:absolute; top:0; right:0; margin:0;
  left:max(40%, calc((100% - var(--maxw)) / 2 + var(--maxw) * 0.4));
  /* Tuned so the box stays near 3.5:1 across the desktop range (~3.4 at
     1920, ~3.5 at 1440, ~3.6 at 1100), because that is the aspect the
     clip path is tuned at — objectBoundingBox normalises to the box, so
     the wave stretches with it and a squatter box visibly steepens the
     descent. Height is therefore NOT a free style knob: change it and
     re-check the measured box aspect, not just whether the height
     "looks right" on its own. */
  height:clamp(170px,16.5vw,360px);
}
/* The clip goes on the <img>, not on .around-photo itself:
   .around-photo-caption is a child of the same figure, and clipping the
   container would clip the caption along with the photo. */
.around-photo-img{
  width:100%; height:100%; object-fit:cover;
  clip-path:url(#aroundWave); display:block;
}
/* Owner-supplied lettering artwork (images/adventuretext.webp), not live
   text — see the note in index.html. Nothing here sets a font, a tilt or
   a stagger any more: the artwork carries all three itself, which is why
   the old .around-photo-caption-line / .around-photo-squiggle rules are
   gone rather than kept "just in case". If it ever goes back to live
   text, those need rebuilding; git history has them.
   --script is still used by .dist-more ("More to explore") in this same
   section, so it is NOT dead now that the caption doesn't use it. */
.around-photo-caption{
  position:absolute; top:6%; right:5%;
  width:min(30%, 300px);
  /* A drop-shadow filter, not box-shadow: the artwork is transparent
     apart from the strokes, so box-shadow would draw a rectangle round
     the whole image box. This follows the letterforms. Same job the old
     text-shadow did for the live-text version — the photo behind it is
     bright in places and the white strokes need separating from it. */
  filter:drop-shadow(0 2px 10px rgba(0,0,0,.35));
}
.around-photo-caption-img{ width:100%; height:auto; display:block; }

.around-grid{ display:grid; grid-template-columns:.9fr 1.1fr; gap:var(--around-gap); }

.dist-head{ display:flex; justify-content:space-between; align-items:baseline; gap:12px; flex-wrap:wrap; }
.dist-col-label{
  margin:0 0 .9em; font:700 .68rem/1 var(--sans); letter-spacing:.1em;
  text-transform:uppercase; color:var(--ink-mute);
}
.dist ul{ list-style:none; margin:0; padding:0; border-top:1px solid var(--line); }
.dist li{
  display:flex; align-items:center; gap:16px;
  padding:.9em 0; border-bottom:1px solid var(--line);
}
.dist-icon{
  display:flex; align-items:center; justify-content:center; flex:none;
  width:38px; height:38px; border-radius:50%;
  background:rgba(28,58,49,.08); color:var(--ink);
}
.dist-icon svg{ width:18px; height:18px; }
.dist-text{ display:flex; flex-direction:column; gap:.25em; flex:1 1 auto; min-width:0; }
.dist-text b{ font-family:var(--serif); font-weight:500; font-size:var(--t-0); }
.dist-text small{ font-size:var(--t--1); color:var(--ink-mute); }
.dist-value{
  display:flex; align-items:center; gap:.35em; flex:none;
  font-family:var(--serif); font-weight:500; white-space:nowrap;
}
.dist-value svg{ width:15px; height:15px; color:var(--ink-mute); }
.dist-more{
  display:flex; align-items:center; gap:14px; margin:1.4em 0 0;
  font-family:var(--script); font-size:1.4rem; color:var(--ink-soft);
}
.dist-more::after{ content:""; flex:1 1 auto; height:1px; background:var(--line); }

/* Only wraps the <h3> now — the "Explore the area" link that used to sit
   opposite it was removed (Sept 2026, owner's request). Kept rather than
   unwrapped because `.h-min`'s margin-bottom:0 here is what leaves the
   spacing below the heading to `.trips p`'s own margin-top; drop the
   wrapper and the two margins start stacking. */
.trips-head{ display:flex; justify-content:space-between; align-items:baseline; gap:16px; flex-wrap:wrap; }
.trips-head .h-min{ margin-bottom:0; }
.trips p{ margin-top:1em; color:var(--ink-soft); }
/* Each group's label needs to sit clearly closer to ITS OWN chips than
   to the group above — it was `margin-top:1.6em` against the chips'
   `margin-top:1.4em`, near enough equal that the label read as a
   trailing caption on the previous group rather than a heading for the
   next one. Roughly 3:1 now. */
.chips-group + .chips-group-label{ margin-top:2.4em; }
.chips-group-label{ margin-bottom:0; }

.chips{ list-style:none; margin:.85em 0 0; padding:0; display:flex; flex-wrap:wrap; gap:9px 10px; }
.chips li{
  font-size:var(--t--1); line-height:1.4;
  padding:.44em .95em;
  background:var(--chalk); border-radius:100px;
  color:var(--ink-soft);
}

/* Some chips are plain place names; others (operators and tourism sites
   with their own pages) are real external links. They used to look
   identical until you hovered, which gave no reason to try hovering in
   the first place — linked ones now carry a small outbound arrow and
   slightly stronger text colour, so the difference is visible at rest. */
.chips li:has(a){ padding:0; }          /* padding moves to the <a> below */
.chips a{
  display:inline-flex; align-items:center; gap:.42em;
  padding:.44em .95em; border-radius:100px;
  color:var(--ink); text-decoration:none;
  transition:background-color .2s ease, color .2s ease;
}
/* :has() is the clean way to hand the padding to the <a> so the WHOLE
   pill is the hit target rather than just the words. Browsers without it
   (nothing current, but just in case) still get a perfectly usable chip:
   the <li> keeps its own padding and the <a> simply sits inside it,
   slightly smaller. Nothing breaks, so this needs no fallback. */
.chips a::after{
  content:""; flex:none; width:.85em; height:.85em;
  background:currentColor; opacity:.5;
  /* A bare diagonal arrow, not the usual box-with-arrow outbound glyph:
     at ~9px rendered, the box collapses into noise. Same lesson as the
     .dist-icon elephant — under ~20px, drop detail rather than shrink
     it. Masked rather than inlined per link so it inherits currentColor
     and the markup stays 11 <svg>s lighter. */
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 16 16 8'/%3E%3Cpath d='M9.5 8H16v6.5'/%3E%3C/svg%3E") center/contain no-repeat;
          mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 16 16 8'/%3E%3Cpath d='M9.5 8H16v6.5'/%3E%3C/svg%3E") center/contain no-repeat;
  transition:opacity .2s ease, transform .2s ease;
}
.chips a:hover{ background:var(--ink); color:var(--chalk); }
.chips a:hover::after{ opacity:.95; transform:translate(1px,-1px); }
.chips a:focus-visible{ background:var(--ink); color:var(--chalk); }

/* ---------- gallery ---------- */
.grid-gal{ display:grid; grid-template-columns:repeat(3,1fr); gap:clamp(8px,1.2vw,16px); }
.gal-item{ padding:0; border:0; background:none; cursor:zoom-in; overflow:hidden; border-radius:var(--r); }
.gal-item img{ width:100%; aspect-ratio:4/3; object-fit:cover; transition:transform .45s ease, filter .45s ease; }
.gal-item:hover img{ transform:scale(1.04); filter:saturate(1.08); }

/* homepage gallery only: one wide tile (2 cols, still just 1 row — an
   8/3 banner-ish crop) per row of 3, alternating which side it falls on
   — tile 1 wide, tile 2 narrow, then tile 3 narrow, tile 4 wide, then
   back to wide-first, and so on. `:nth-child(4n+1)` and `:nth-child(4n)`
   land on exactly the tiles that pattern needs wide (1,4,5,8,9,12,13…);
   everything else stays the grid's default 1-col/4:3 tile. This is a
   repeating formula rather than the fixed 1st/4th/5th list it used to be
   (that only worked for exactly 6 photos) specifically so it keeps
   working as "See more photos" (script.js) reveals photos past 6 — see
   CLAUDE.md § Image status. Scoped to `.grid-gal-mosaic` rather than left
   as a bare `.grid-gal` default, since a `.grid-gal` with a different
   photo count (every room page) needs a different pattern, see
   `.grid-gal-feature` below. */
.grid-gal-mosaic .gal-item:nth-child(4n+1),
.grid-gal-mosaic .gal-item:nth-child(4n){ grid-column:span 2; }
.grid-gal-mosaic .gal-item:nth-child(4n+1) img,
.grid-gal-mosaic .gal-item:nth-child(4n) img{ aspect-ratio:8/3; }
/* Opt-out for a row of equal tiles (the three breakfast plates). Same
   specificity as the nth-child rules above and later in the file, so it
   wins. The row before it must already be full (a wide + a narrow tile),
   or these three won't start a row of their own. */
.grid-gal-mosaic .gal-item.gal-item--trio{ grid-column:span 1; }
.grid-gal-mosaic .gal-item.gal-item--trio img{ aspect-ratio:4/3; }

/* room-page galleries: just the first photo as a big 2×2 feature tile,
   ported from the reference site's gallery (their `.gallery
   button:first-child{grid-column:span 2;grid-row:span 2}`). Every other
   tile stays a plain 1×1 cell at the grid's default 4/3 aspect ratio, so
   the two rows the feature tile spans line up with the grid's own auto
   rows — and unlike the mosaic above, this generalises to any photo
   count, not just a fixed set of six. */
.grid-gal-feature .gal-item{ grid-column:span 1; grid-row:span 1; }
.grid-gal-feature .gal-item img{ aspect-ratio:4/3; }
.grid-gal-feature .gal-item:first-child{ grid-column:span 2; grid-row:span 2; }

/* homepage gallery only: photos past the first 6 ship in the DOM already
   (so the lightbox's prev/next can page through all of them from the
   start) but sit `hidden` until "See more photos" reveals them 4 at a
   time — see the #galMore handler in script.js. */
.gal-more-row{ display:flex; justify-content:center; margin-top:clamp(28px,4vw,40px); }
/* .btn's own `display:inline-flex` and [hidden]'s UA-stylesheet
   `display:none` are the same specificity, so without this, JS setting
   `galMore.hidden = true` doesn't actually hide it — the author-stylesheet
   .btn rule wins the tie against the browser's default [hidden] rule
   (same specificity, but UA-origin rules always lose ties to an author
   rule, regardless of order). This re-asserts it at author-stylesheet
   specificity so the button actually disappears once every photo has
   been revealed. */
.gal-more-row .btn[hidden]{ display:none; }

/* must be `fixed`, not `relative` — `<dialog>`'s own UA stylesheet
   expects `position:fixed` to centre itself in the viewport via
   `inset:0; margin:auto`. Overriding that to `relative` (as this used to)
   boxes the dialog into whatever positioned ancestor wraps the gallery
   instead of the viewport — cropped/offset image, backdrop not covering
   the screen, and (since the browser scrolls a just-shown modal into
   view, and a `relative` dialog sitting mid-page isn't "in view" yet) a
   jarring scroll-to-top on open. `fixed`+`inset:0`+`margin:auto` keeps it
   viewport-centred regardless of scroll position, which also makes the
   open-time scroll-jump a non-issue since the dialog never needs
   scrolling into view. */
.lb{ position:fixed; inset:0; margin:auto; border:0; padding:0; background:transparent; max-width:min(94vw,1100px); overflow:visible; }
.lb::backdrop{ background:rgba(16,34,28,.9); }
.lb img{ display:block; width:auto; height:auto; max-width:100%; max-height:90vh; border-radius:var(--r); }
.lb-close{
  position:absolute; top:12px; right:12px; z-index:2;
  width:40px; height:40px; border-radius:50%;
  background:rgba(16,34,28,.72); border:0;
  color:#fff; font-size:1.6rem; line-height:1; cursor:pointer;
}
.lb-close:hover{ background:rgba(16,34,28,.92); }
/* fixed to the viewport, not `.lb` — `.lb`'s own width/height shrink to
   fit whichever photo is showing (capped by max-width/max-height), so a
   narrower portrait shot made `absolute`-positioned arrows creep inward
   with it instead of staying put; `fixed` with a flat edge offset keeps
   them anchored to the sides of the screen regardless of the current
   photo's aspect ratio. */
.lb-nav{
  position:fixed; top:50%; transform:translateY(-50%); z-index:2;
  width:44px; height:44px; border-radius:50%;
  background:rgba(16,34,28,.72); border:0; color:#fff;
  font-size:1.7rem; line-height:1; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
}
.lb-nav:hover{ background:rgba(16,34,28,.92); }
.lb-prev{ left:clamp(10px,3vw,28px); }
.lb-next{ right:clamp(10px,3vw,28px); }
.lb-count{
  position:absolute; left:50%; bottom:12px; transform:translateX(-50%); z-index:2;
  margin:0; padding:.35em .9em; border-radius:100px;
  background:rgba(16,34,28,.72); color:#fff; font-size:12px; letter-spacing:.02em;
}

/* ---------- callback ---------- */
/* This section closes with .cb-signoff, which already sits a long way
   down (see its margin-top). A full --band of padding *underneath* that
   as well left an obvious slab of empty colour at the bottom, so the
   bottom padding is roughly halved here, same as .band's own bottom
   default everywhere else — they're deliberately not symmetrical. Top
   padding is untouched, so it opens with the same (now sitewide-default)
   eyebrow gap as every other section — see "BANDS" above. */
.cb-band{ padding-bottom:clamp(40px,5vw,70px); }
.cb{ display:grid; grid-template-columns:1fr; align-items:start; }
/* Left-aligned and full-width, NOT the centred 800px block this was —
   the owner asked for it on the left, and the card/facts layout below
   needs the room. The lede keeps its own narrower measure (below) so
   only the two columns use the full width.

   This section used to be a two-column grid (.cb-intro | .cb-form) and
   carried a `cb--solo` modifier while the form was hidden. The form was
   scrapped for good (Sept 2026), so the modifier is folded into .cb and
   there is no second column to reserve. */
.cb .cb-intro{ max-width:none; margin:0; }
.cb .cb-intro > .lede{ max-width:52ch; }

/* Two equal columns with a hairline between them. The divider is a
   border on the second column rather than a separate element, so it
   stretches to whichever column is taller on its own. */
.cb .cb-cols{
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(32px,5vw,72px); align-items:stretch;
  margin-top:clamp(32px,4vw,54px);
}
.cb .cb-col--facts{ border-left:1px solid var(--line); padding-left:clamp(32px,5vw,72px); }
.cb .cb-cols .cb-gk{ margin-top:0; }

/* ---- contact cards ---- */
.cb-direct{ list-style:none; margin:1.4em 0 0; padding:0; display:grid; gap:12px; border:0; }
.cb-direct li{ display:block; padding:0; border:0; }
.cb-card{
  display:flex; align-items:center; gap:16px;
  padding:14px 18px;
  border:1px solid var(--line); border-radius:14px;
  /* A solid --chalk fill, not the translucent white this had while the
     section sat on the rose band. On the --paper band a 35%-white card
     is all but invisible; --chalk is a step DARKER than --paper, so the
     cards read as cards, and on hover they brighten to white — the state
     change runs light rather than dark, which is why the border darkens
     at the same time to keep the edge defined. */
  background:var(--chalk);
  text-decoration:none; color:var(--ink);
  transition:background-color .2s ease, border-color .2s ease, transform .2s ease;
}
.cb-card:hover{ background:#fff; border-color:var(--ink-mute); transform:translateY(-1px); }
.cb-card-icon{
  display:grid; place-items:center; flex:none; width:44px; height:44px;
  border-radius:50%; background:rgba(28,58,49,.08); color:var(--ink);
}
.cb-card-icon svg{ width:20px; height:20px; }
.cb-card-text{ display:flex; flex-direction:column; gap:.25em; flex:1 1 auto; min-width:0; }
.cb-card-label{
  font:700 .68rem/1 var(--sans); letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-mute);
}
.cb-card-value{ font-family:var(--serif); font-weight:500; font-size:var(--t-1); }
/* The email is much longer than the phone numbers, so it gets its own
   smaller, fluid size — at a fixed size it wrapped mid-address on phones
   ("…co.z / a"), which looks like a typo rather than a line break. The
   vw term lets it shrink to fit the card on narrow screens; the ceiling
   keeps it at --t-0 everywhere else. overflow-wrap stays as a
   last-resort guard against overflow if the address ever changes. */
.cb-card-value--sm{ font-size:clamp(.84rem,3.3vw,var(--t-0)); overflow-wrap:anywhere; }
.cb-card-go{ flex:none; color:var(--ink-mute); transition:transform .2s ease, color .2s ease; }
.cb-card-go svg{ width:20px; height:20px; display:block; }
.cb-card:hover .cb-card-go{ transform:translateX(3px); color:var(--ink); }

/* ---- "Good to know" facts, icon-led ---- */
.cb-facts dt{ display:flex; align-items:center; gap:14px; }
.cb-facts > div{ padding:.95em 0; }
.cb-fact-icon{
  display:grid; place-items:center; flex:none; width:38px; height:38px;
  border-radius:50%; background:rgba(28,58,49,.08); color:var(--ink);
}
.cb-fact-icon svg{ width:18px; height:18px; }
.cb-facts dt{
  font:700 .68rem/1 var(--sans); letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-mute);
}
.cb-facts dd{ font-size:var(--t-0); }

/* ---- closing line ---- */
/* Same rule-flanked script line as .dist-more, but centred rather than
   trailing, so it reads as a sign-off for the whole section. */
.cb-signoff{
  display:flex; align-items:center; gap:clamp(18px,3vw,32px);
  /* Sits well clear of the columns above it — it's a sign-off for the
     whole section, not a caption on the facts list, and it needs the
     distance to read that way. */
  margin:clamp(62px,7.5vw,104px) 0 0;
  font-family:var(--script); font-size:clamp(1.45rem,2.4vw,1.9rem);
  color:var(--ink-soft); text-align:center;
}
.cb-signoff::before,.cb-signoff::after{ content:""; flex:1 1 auto; height:1px; background:var(--line); }

/* Two side-by-side columns with a divider stop working once each is
   phone-width, so they stack — and the divider has to move with them:
   a left border on a full-width block would draw a stray vertical line
   down the page. It becomes the gap above the second block instead. */
@media (max-width:760px){
  .cb .cb-cols{ grid-template-columns:minmax(0,1fr); gap:0; }
  .cb .cb-col--facts{ border-left:0; padding-left:0; }
  .cb .cb-cols .cb-gk{ margin-top:2.4em; }
}

.cb-gk{ margin-top:2.2em; }


/* ---------- find us ---------- */
.find-grid{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:clamp(28px,4vw,56px); }
.find-col address{ font-style:normal; color:var(--ink-soft); line-height:1.75; }
.dir{ border-top:1px solid var(--line); }
.dir:last-of-type{ border-bottom:1px solid var(--line); margin-bottom:1.6em; }
.dir summary{
  cursor:pointer; padding:.85em 0; font-weight:600; font-size:var(--t-0);
  list-style:none; display:flex; justify-content:space-between; align-items:center;
}
.dir summary::-webkit-details-marker{ display:none; }
.dir summary::after{ content:"+"; font-size:1.3rem; color:var(--rose); line-height:1; }
.dir[open] summary::after{ content:"\2013"; }
.dir p{ color:var(--ink-soft); font-size:var(--t--1); padding-bottom:.4em; }
.find-map{ grid-column:1 / -1; }
.find-map iframe{ width:100%; height:clamp(300px,42vw,440px); border:1px solid var(--line); border-radius:var(--r); }

/* ============================================================
   FOOTER
   ============================================================ */
.site-foot{ background:var(--ink); color:var(--chalk); padding-block:clamp(44px,6vw,72px); }
.foot-inner{ display:grid; gap:28px; }
.foot-brand{ display:flex; align-items:center; gap:14px; }
.foot-brand p{ margin:0; font-size:var(--t--1); color:rgba(239,242,234,.78); }
.foot-nav{ display:flex; flex-wrap:wrap; gap:10px 26px; padding-top:24px; border-top:1px solid var(--line-light); }
.foot-nav a{ font-size:var(--t--1); text-decoration:none; color:rgba(239,242,234,.86); }
.foot-nav a:hover{ color:#fff; text-decoration:underline; }
.foot-legal{ margin:0; font-size:var(--t--1); color:rgba(239,242,234,.55); }

/* ---------- whatsapp float ---------- */
/* A labelled pill rather than a bare icon, so it says what it's for. The
   close button doesn't remove it: it shrinks it to the round icon (still a
   working link), and script.js remembers that per browser. The label is
   aria-hidden because the link's aria-label already carries the same
   words and has to keep working once the label is hidden. */
.wa-float{
  position:fixed; right:18px; bottom:18px; z-index:80;
  animation:wa-in .45s ease-out .9s both;
}
@keyframes wa-in{ from{ opacity:0; transform:translateY(14px); } }
.wa-float-link{
  display:flex; align-items:center; gap:12px;
  padding:6px 22px 6px 6px; border-radius:100px;
  background:var(--paper); border:1px solid var(--line); color:var(--ink);
  text-decoration:none;
  box-shadow:0 10px 30px rgba(16,34,28,.16), 0 2px 6px rgba(16,34,28,.08);
  transition:transform .2s ease, box-shadow .2s ease;
}
.wa-float-link:hover{ transform:translateY(-2px); box-shadow:0 14px 34px rgba(16,34,28,.22), 0 2px 6px rgba(16,34,28,.08); }
.wa-float-icon{
  display:grid; place-items:center; flex:none;
  width:44px; height:44px; border-radius:50%;
  background:var(--ink); color:#fff; transition:background-color .2s ease;
}
.wa-float-link:hover .wa-float-icon{ background:var(--sea); }
.wa-float-icon svg{ width:23px; height:23px; fill:currentColor; }
.wa-float-text{ display:flex; flex-direction:column; }
.wa-float-title{ font:500 1.0625rem/1.15 var(--serif); letter-spacing:-.005em; }
.wa-float-sub{ font-size:.8125rem; line-height:1.3; color:var(--ink-mute); margin-top:2px; }
.wa-float-close{
  position:absolute; top:-7px; right:-7px;
  display:grid; place-items:center; width:24px; height:24px; padding:0;
  border:2px solid var(--paper); border-radius:50%;
  background:var(--ink); color:#fff; cursor:pointer;
  transition:background-color .2s ease;
}
.wa-float-close:hover{ background:var(--sea); }
.wa-float-close svg{ width:10px; height:10px; }
.wa-float.is-min .wa-float-text,
.wa-float.is-min .wa-float-close{ display:none; }
.wa-float.is-min .wa-float-link{ padding:4px; }
@media (prefers-reduced-motion:reduce){
  .wa-float{ animation:none; }
  .wa-float-link, .wa-float-icon{ transition:none; }
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width:1080px){
  .rooms{ grid-template-columns:repeat(2,1fr); }
  .amen-list{ grid-template-columns:repeat(3,1fr); }
}

@media (max-width:900px){
  .split, .around-grid{ grid-template-columns:1fr; }
  /* .around-photo's desktop layout (absolute, spanning the right half of
     the section) has no room to work with at this width — back to a
     normal-flow, full-width block above the text. .sec-head's min-height
     exists only to reserve space under the absolute photo, and its
     max-width only to keep the lede clear of it, so both drop away once
     the photo is back in flow ahead of it.

     padding-top is 0 so the photo still starts flush with the band's
     colour boundary, exactly as it does on desktop. It was --band here
     (~64px+), which left a strip of empty paper colour between the
     previous section and the top of the photo — it read as a gap, not a
     margin. The photo's own margin-bottom below supplies the space
     before the text. */
  .around{ padding-top:0; }
  .around-top{ margin-bottom:28px; }
  .around-top .sec-head{ min-height:0; max-width:none; }
  /* position:relative, not static — .around-photo-caption is positioned
     absolute against it, so losing the positioning context here (static
     would fall through to .around{position:relative} instead, the
     section itself) sent the caption flying up into the cream space
     above the photo the first time this was tried. */
  .around-photo{ position:relative; top:auto; left:auto; right:auto; width:100%; height:min(55vw,260px); margin-bottom:28px; }
  .split-fig{ position:static; }
  /* 16/10 is a landscape window onto a 3/4 portrait photo, so only ~47% of
     its height shows and this value picks WHERE on the photo that window
     sits: 0% = the very top, 100% = the very bottom. The owner has steered
     it by eye (Sept 2026) — 50% centred, then 60% and 72% (deckchair, pot
     and paving, little of the creeper), and finally "much higher": 8%,
     which is mostly the full creeper in flower with sky above it. Note
     "lower"/"higher" meant the WINDOW's position on the photo, not the
     picture moving in its frame; that was read backwards twice at first.
     Only vertical position matters here; the width always fits. */
  .split-fig img{ aspect-ratio:16/10; object-position:center 8%; }
  .find-grid{ grid-template-columns:1fr; }
  .ribbon{ grid-template-columns:repeat(2,1fr); }
  .ribbon li{ border-top:1px solid var(--line-light); padding-inline:var(--gut); }
  .ribbon li:nth-child(-n+2){ border-top:0; }
  .ribbon li:nth-child(odd){ border-left:0; }

  /* minmax(0,1fr), not a bare 1fr — a grid item's default min-width is
     "auto", which still respects a deep descendant's intrinsic content
     width (e.g. anything nowrap); a bare 1fr track will happily grow
     past the viewport to fit that instead of letting it wrap, pushing
     the whole page into horizontal scroll. minmax(0,…) is what actually
     lets the track (and everything in it) shrink below its content. */
  .roomlayout{ grid-template-columns:minmax(0,1fr); }
  /* Cap the width once it stops being a 340px sidebar and becomes a
     standalone block. Left un-capped it took the full column — 809px at
     899px viewport — and the card doesn't survive that: .bookbox-head's
     aspect-ratio (see its own comment) scales the wave photo's height
     with the card's width, so a 2.4x-wider card gets a 270px-tall photo
     banner instead of the ~114px it's designed around, and the facts
     rows below strand their label at the far left and value at the far
     right with a void between. 440px is the sidebar's own width plus a
     little, so the card reads the same as it does on desktop. */
  .roomlayout-aside{
    position:static; margin-bottom:clamp(24px,4vw,40px);
    max-width:440px;
  }
}

/* header/nav switches to the burger menu at a much wider breakpoint than
   the rest of the mobile layout below (1024px, not 760px). The desktop
   nav has five links plus a phone number and a solid button all in one
   row — measured against the available header width, that only has
   ~13px of slack left over at 900px viewport (the point the rest of the
   page collapses to a single column at), which is basically zero margin:
   the moment webfont metrics come out even slightly wider than expected
   (a real browser vs. this dev setup, fonts not yet loaded, etc.) it
   wraps mid-link ("Around us" splitting into "Around" / "us") and the
   header grows tall enough to eat into the hero title below it. 1024px
   leaves a safe ~100px+ of slack instead. Kept as its own media query
   rather than folding into the block below so the rest of that block's
   breakpoint (where cards/galleries/forms go single-column) is untouched. */
@media (max-width:1024px){
  /* No scroll-padding-top override here — the header is --head-h tall at
     every width, so the base rule is already correct. There used to be a
     74px one, which undershot the 76px header and tucked the top of each
     target section under it. */
  .nav{
    position:absolute; inset:100% 0 auto 0;
    flex-direction:column; gap:0;
    background:var(--paper); color:var(--ink);
    border-top:1px solid var(--line);
    padding:6px var(--gut) 18px;
    display:none;
  }
  .nav.open{ display:flex; }
  .nav a{ padding:13px 0; border-bottom:1px solid var(--line); font-size:var(--t-0); }
  .nav a::after{ display:none; }
  .burger{ display:block; }
  .head-actions .btn{ display:none; }
  .site-head.stuck .nav{ background:var(--paper); }

  /* no hover on touch, so the "Rooms" dropdown just renders open and
     inline instead — a plain indented sub-list under the Rooms link,
     rather than the floating hover panel used at desktop widths */
  .nav-caret{ display:none; }
  .nav-dropdown{
    position:static; opacity:1; visibility:visible; transform:none;
    margin:0 0 4px; padding:0 0 4px 16px; border:0; box-shadow:none;
    background:none; border-radius:0;
  }
  .nav-dropdown a{ padding:10px 0; font-size:var(--t--1); color:var(--ink-mute); }
}

@media (max-width:760px){
  .rooms{ grid-template-columns:1fr; }

  .amen-list{ grid-template-columns:repeat(2,1fr); }
  .grid-gal{ grid-template-columns:repeat(2,1fr); }
  .grid-gal-mosaic .gal-item:nth-child(n){ grid-column:span 1; }
  .grid-gal-mosaic .gal-item:nth-child(n) img{ aspect-ratio:4/3; }
  .grid-gal-feature .gal-item:first-child{ grid-column:span 2; grid-row:span 1; }
}

@media (max-width:460px){
  .amen-list{ grid-template-columns:1fr; }
  .ribbon li{ padding-block:16px; }
  .ribbon strong{ font-size:var(--t-0); }
  .brand-sub{ display:none; }
  .hero-cta .btn{ width:100%; }
}

@media print{
  .site-head, .wa-float, .find-map, .burger{ display:none; }
  body{ background:#fff; color:#000; }
}
