/* =============================================================================
   STAYHUB GUEST, COMPONENTS
   Everything the Stayhub Hostaway plugin renders, skinned to the Figma
   direction: hero + search, Get inspired tiles, the asymmetric Featured
   properties grid, stay types, live reviews, travel guides, the split CTA,
   the coral sign-up band, results grid, listing detail and the mock checkout.

   Class names are the contract between the plugin's markup and this file, so
   the whole site can be restyled here without touching PHP.
   ============================================================================= */

/* ======================================================================= HERO */

/* THE ONE SCULPTED CORNER on the home page. The device is used exactly once
   per page (see --r-hero in base.css); everything below this point takes the
   quiet 12px card radius instead.

   ROUND 4, fix 1. Rebuilt against the exported Figma frame, which is kept at
   booking-site-rebuild/examples/figma-hero-reference.png. What the reference
   settles, measured off it rather than eyeballed:

     photograph      full bleed, 598 of the frame's 1372px, so a fraction under
                     600px tall on a laptop
     heading         MAROON over the picture, not white, and vertically centred
                     with the search bar rather than sitting on the floor
     the sweep       the bottom-right quarter round measures ~250px, and the
                     colour inside it is #FAE4D3, the same light orange as the
                     tagline band, so the block below reads as sweeping up into
                     the photograph
     side margin     ~60px at 1372px wide, which is wider than the site's own
                     1240px wrap. This is the one thing the hero does NOT copy;
                     the reasoning is written out beside .sh-wrap in base.css,
                     along with the one rule that reverses it.

   The shell is what carries the light orange behind the clipped corner. The
   photograph cannot paint it: it is the thing being cut away. */
.sh-hero-shell { background: var(--lorange); }
/* ROUND 6, Joanne's fix 1. Two changes to the box itself:

   SHORTER. 600px filled a 13in laptop viewport under the header and gave the
   guest nothing to suggest the page continued. 520px, capped at 74vh, puts the
   top of Perks of Booking Direct on screen at every common laptop height,
   which is the whole reason Fiona asked for it.

   A MEDIA LAYER instead of a background-image. The hero now holds a poster
   <img> and, once chrome.js promotes it, a <video> on top. Both are absolutely
   positioned and object-fit cover, so they crop exactly as the old background
   did, and the sweep still clips them because the section owns the radius and
   the overflow. */
.sh-hero {
	position: relative;
	min-height: min(520px, 74vh);
	display: flex;
	align-items: center;
	background: var(--maroon-deep);
	border-radius: 0 0 var(--r-hero-sweep) 0;
	overflow: hidden;
	padding: var(--space-2xl) 0;
}
.sh-hero-media { position: absolute; inset: 0; z-index: 0; }
.sh-hero-media > img,
.sh-hero-video {
	position: absolute; inset: 0;
	width: 100%; height: 100%;
	object-fit: cover;
	display: block;
}
/* The poster stays in the DOM under the video, so a video that stalls mid-play
   reveals a photograph rather than a black rectangle. It fades rather than
   cuts, because the video's first frame IS the poster and a hard swap reads as
   a flicker. */
.sh-hero-media > img { transition: opacity .5s ease; }
.sh-hero-media.has-video > img { opacity: 0; }
.sh-hero-video { opacity: 0; transition: opacity .5s ease; }
.sh-hero-media.has-video .sh-hero-video { opacity: 1; }
/* #189, and now doubly so: the heading is maroon, so a dark scrim would work
   against it rather than for it. What is left is a soft LIGHT wash weighted to
   the top left, where the type sits. On the reference photograph (pale sky) it
   is all but invisible, which is the point; on a darker hero image it is what
   keeps maroon type legible instead of leaving it to luck. */
.sh-hero::after {
	content: "";
	position: absolute; inset: 0;
	background: linear-gradient(118deg, rgba(247,245,240,.62) 0%, rgba(247,245,240,.30) 34%, rgba(247,245,240,0) 62%);
}
.sh-hero > .sh-wrap { position: relative; z-index: 2; width: 100%; }
.sh-hero h1 {
	color: var(--maroon);
	font-size: clamp(2.2rem, 4.2vw, 3.5rem);
	max-width: 15ch;
	margin-bottom: 0;
}
/* ROUND 6: the brand subhead moves inside the hero, under the H1, which is
   where the interim site has it and where Fiona wants it ("a subhead line in
   the hero image instead of a text callout underneath the section").

   Set in the BODY face, not the display serif. Two serif lines stacked read as
   one long heading and the H1 stops being the loudest thing on the page; the
   sans keeps the hierarchy honest and matches the interim site's own
   treatment. */
.sh-hero-sub {
	font-family: var(--sh-body);
	font-size: clamp(1rem, 1.5vw, 1.22rem);
	font-weight: 600;
	color: var(--maroon);
	max-width: 46ch;
	margin: 12px 0 var(--space-lg);
}

/* ---------------------------------------------- the search bar (fix 1)
   #188 asked for one calm banner rather than a busy strip, and the reference
   image is emphatic about what that means: ONE continuous white bar with
   hairline rules between the segments, not five boxed fields in a card. Each
   segment is a single line of maroon type, centred in a 58px bar, with a
   chevron on the three selects. The acid Search pill sits at the right hand
   end, the same height as the bar with a hair of daylight between them.

   Widths are even across the segments, as they are in the reference. We carry
   five where the frame had four (Departure), so the bar is a little wider in
   proportion; it still stops well short of the right edge, which is what keeps
   the photograph and the sweep readable behind it. */
.sh-search {
	display: flex;
	align-items: stretch;
	gap: 8px;
	/* The bar stops short of the right hand edge, as it does in the reference,
	   so the photograph and the sweep still read behind it. */
	max-width: 1060px;
}
.sh-search-bar {
	flex: 1 1 auto;
	min-width: 0;
	display: grid;
	/* FOUR segments now: the two date fields became one range control
	   (1 Oct 2026), so the bar is Dates, Location, Bedrooms, Guests. */
	grid-template-columns: repeat(4, minmax(0, 1fr));
	background: var(--white);
	border-radius: var(--r-card);
	box-shadow: 0 18px 40px rgba(22,18,13,.16);
	overflow: hidden;
}
.sh-seg { position: relative; min-width: 0; }
/* The hairline between segments. An inset pseudo-element rather than a border,
   because the rule stops short of the top and bottom of the bar in the
   reference rather than running the full height. */
.sh-seg + .sh-seg::before {
	content: "";
	position: absolute; left: 0; top: 22%; bottom: 22%;
	width: 1px;
	background: #E4E3E0;
}
/* The label is kept for screen readers and for the field's own accessible
   name; the visible label is the segment's empty state, per the reference. */
.sh-seg-label {
	position: absolute;
	width: 1px; height: 1px;
	margin: -1px; padding: 0;
	overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
	white-space: nowrap;
}
/* Restated inside the bar rather than left to the global field styling, which
   is boxed, bordered and rounded. Inside the bar a segment is not a box. */
.sh-search-bar input,
.sh-search-bar select {
	width: 100%;
	height: 58px;
	min-height: 58px;
	background-color: transparent;
	border: none;
	border-radius: 0;
	color: var(--maroon);
	font-size: 1rem;
	padding: 0 20px;
}
.sh-search-bar select { padding-right: 40px; background-position: right 16px center; }
.sh-search-bar input:focus,
.sh-search-bar select:focus {
	box-shadow: inset 0 0 0 2px var(--maroon);
	border-radius: var(--r-ctl);
	outline: none;
}
.sh-search-bar input[type="date"] { color-scheme: light; }
/* The date segments' empty state. A date input has no placeholder, so this is
   an opaque overlay sitting on top of the browser's own date mask until the
   guest picks a day. It stops short of the right hand edge so the native
   calendar button stays visible and clickable. */
.sh-seg-ph {
	position: absolute;
	left: 1px; right: 34px; top: 1px; bottom: 1px;
	display: flex; align-items: center;
	padding-left: 19px;
	background: var(--white);
	color: var(--maroon);
	font-size: 1rem;
	pointer-events: none;
}
.sh-seg.is-filled .sh-seg-ph { display: none; }
.sh-search-go { flex: 0 0 auto; padding: 15px 40px; }

/* ========================================================= NO BS, AS A FEATURE */

/* ROUND 6, Joanne's fix 2: "And then having the 'No BS' as a separate
   feature." Through rounds 4 and 5 this was the three-line block directly under
   the hero, carrying the location line, the care line and the payoff. The first
   two are the hero's subhead now, so what is left is the payoff, and it gets to
   behave like a statement instead of a third line.

   Centred, which is the one place on the site that is. Everything else is left
   aligned to a single edge (round 3, fix 6), and that is exactly what makes a
   centred band read as a deliberate pause rather than a stray. It sits directly
   above the Stayhub Difference band and the two are designed as one move: the
   claim, then the evidence.

   The Seasons ships in one weight, so the emphasis is a real evenly applied
   stroke rather than the browser's smeared synthetic bold. */
.sh-nobs {
	background: var(--lorange);
	padding: var(--space-3xl) 0;
	text-align: center;
}
.sh-nobs-line {
	font-family: var(--sh-display);
	font-size: clamp(2rem, 4.6vw, 3.9rem);
	line-height: 1.08;
	letter-spacing: -0.01em;
	color: var(--maroon);
	-webkit-text-stroke: 0.9px var(--maroon);
	margin: 0 auto;
	max-width: 18ch;
}
.sh-nobs-body {
	font-size: 1.12rem;
	color: var(--maroon);
	max-width: 56ch;
	margin: var(--space-md) auto 0;
}

/* ================================================== PERKS OF BOOKING DIRECT */

/* ROUND 6, Joanne's fix 3, the section Rod asked for and the prototype was
   missing. Three even columns, the interim site's shape: the one-word label,
   the square graphic tile, the promise in weight, then the detail.

   It sits directly under the hero, so the light orange of the hero's sweep runs
   into a cream section and the eye keeps moving. The graphics are maroon-ground
   squares, which is a lot of dark on a pale page, so the tiles are held at a
   1:1 box and given the quiet card radius rather than any of the big ones: they
   are content, not structure.

   Square is also the reason the grid does not reflow when Hariel's replacements
   land at a different pixel size. */
.sh-perk-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--sh-gap-row) var(--sh-gap);
}
.sh-perk-label {
	font-family: var(--sh-body);
	/* Bigger than the 1rem it was: these three words are what the column is
	   about, and at body size they read as a caption rather than a heading. */
	font-size: clamp(1.4rem, 1.15rem + 0.8vw, 1.9rem);
	font-weight: 600;
	line-height: 1.1;
	letter-spacing: -0.01em;
	color: var(--coral);
	margin: 0 0 var(--space-sm);
}
.sh-perk-media {
	/* The brand's rounded-corner device: three corners swept, one left square.
	   The square corner is top left on all three, so the set reads as a family
	   and the eye starts in the same place in each column. */
	border-radius: 0 var(--r-tile) var(--r-tile) var(--r-tile);
	overflow: hidden;
	background: var(--stone);
	/* The photographs' own ratio, so nothing is cropped off a device screen. */
	aspect-ratio: 880 / 758;
	margin-bottom: var(--space-md);
}
.sh-perk-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sh-perk-promise {
	font-weight: 600;
	color: var(--maroon);
	font-size: 1.06rem;
	margin: 0 0 0.8em;
}
.sh-perk-body { color: var(--ink); margin: 0; }

/* ============================================ STAYHUB DIFFERENCE, HOME BAND */

/* ROUND 6, Joanne's fix 6, with Fiona's fix 7 folded into it.

   The composition is the one from Chase's home page that Joanne liked:
   photograph full bleed, copy in white on the left, eyebrow, heading, story,
   payoff, acid pill. The SHAPE is the owners' site's "More Than Management"
   band, which is where Fiona's "a few more curves ... match our owners' website
   a little better" gets answered: a large sculpted corner top-left AND
   bottom-left, so the band is a form rather than a rectangle.

   Two curves on the same side, rather than the hero's single one, is what makes
   this read as a quotation from the owners' site instead of a repeat of the
   hero. The cream page shows through both, which is only true because the band
   is full bleed and the page base is cream everywhere.

   WHITE TYPE, AND WHY IT IS ALLOWED HERE. This is the one place the site sets
   white type, and it earns it with a real gradient scrim weighted to the left
   where the copy sits. Everywhere else the white-on-coral contrast problem is
   solved by not using white at all (maroon on coral is 4.9:1; white is 2.8:1
   and fails). Over a photograph with a scrim underneath it, white clears 4.5:1
   comfortably, and maroon would not. */
.sh-difference {
	position: relative;
	display: flex;
	align-items: center;
	min-height: min(560px, 76vh);
	padding: var(--space-3xl) 0;
	overflow: hidden;
	background: var(--maroon-deep);
	/* TOP-RIGHT and BOTTOM-LEFT: the brand's curves are DIAGONAL, never two on
	   the same side (Fiona, 30 Sep 2026: "we don't put two curves on one side
	   it should be top right and bottom left"). Diagonally opposed corners give
	   the band a rotation, which is the gesture the owners' site is actually
	   making; two on one edge just makes a lozenge. The cream page base shows
	   through both. */
	border-radius: 0 var(--r-hero) 0 var(--r-hero);
	isolation: isolate;
}
.sh-difference-media {
	position: absolute; inset: 0;
	width: 100%; height: 100%;
	object-fit: cover;
	z-index: -2;
}
.sh-difference::after {
	content: "";
	position: absolute; inset: 0;
	z-index: -1;
	background: linear-gradient(92deg, rgba(22,18,13,.82) 0%, rgba(22,18,13,.70) 34%, rgba(22,18,13,.42) 58%, rgba(22,18,13,.08) 84%, rgba(22,18,13,0) 100%);
}
.sh-difference > .sh-wrap { position: relative; z-index: 1; width: 100%; }
.sh-difference-copy { max-width: 52ch; color: #fff; }
.sh-difference-copy .sh-eyebrow { color: var(--lorange); }
.sh-difference-copy h2 {
	color: #fff;
	font-size: clamp(2.1rem, 4.2vw, 3.4rem);
	max-width: 14ch;
	margin-bottom: var(--space-md);
}
.sh-difference-copy p { color: #F6F1EC; }
.sh-difference-payoff { font-weight: 600; color: #fff; }
.sh-difference-copy .sh-btn { margin-top: var(--space-md); }

/* ============================================================== GET INSPIRED */

/* ROUND 3, fix 4: two rows of three with a real gutter in BOTH directions, so
   the tiles stop touching. Six across on a 1240px page gave slivers; three
   across gives each destination a photograph you can actually read. */
.sh-tile-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--sh-gap-row) var(--sh-gap);
}
/* ROUND 6, Joanne's fix 4: Swimming Pool joins the row, which takes it from six
   tiles to seven. Seven across a three-column grid leaves a row of one, so the
   grid becomes twelve columns and runs FOUR across the top, THREE across the
   bottom. Both rows fill the width, nothing had to be dropped to make room, and
   the bottom row's tiles are the wider ones, which is the right way round: the
   regions brand tile lives there and has the most to say.

   Six or fewer tiles falls straight back to the three-column rule above. */
.sh-tile-grid--7 { grid-template-columns: repeat(12, 1fr); }
.sh-tile-grid--7 > * { grid-column: span 3; }
.sh-tile-grid--7 > :nth-child(n+5) { grid-column: span 4; }
.sh-tile {
	position: relative;
	display: block;
	aspect-ratio: 4 / 3;
	border-radius: var(--r-card);
	overflow: hidden;
	background: var(--lorange);
	isolation: isolate;
}
.sh-tile img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.sh-tile:hover img,
.sh-tile:focus-visible img { transform: scale(1.05); }
.sh-tile { transition: box-shadow .18s ease; }
.sh-tile:hover { box-shadow: 0 10px 26px rgba(22,18,13,.16); text-decoration: none; }
.sh-tile:focus-visible { outline: 3px solid var(--maroon); outline-offset: 3px; }
.sh-tile::after {
	content: "";
	position: absolute; inset: 0;
	background: linear-gradient(180deg, rgba(22,18,13,0) 40%, rgba(22,18,13,.36) 68%, rgba(22,18,13,.82) 100%);
}
/* Fix 4, hover: a transparent BRAND COLOUR wash over the photograph, the way
   the live site does it. A second layer over the reading scrim, so the label
   stays legible the whole way through the transition. */
.sh-tile::before {
	content: "";
	position: absolute; inset: 0; z-index: 1;
	background: rgba(92, 14, 7, .52);
	opacity: 0;
	transition: opacity .28s ease;
	pointer-events: none;
}
.sh-tile:hover::before,
.sh-tile:focus-visible::before { opacity: 1; }
.sh-tile-brand:hover::before,
.sh-tile-brand:focus-visible::before { background: rgba(92, 14, 7, .28); }
.sh-tile-label {
	position: absolute; left: 16px; right: 16px; bottom: 16px; z-index: 2;
	font-family: var(--sh-body);
	font-size: 0.8rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: #FFF9F4;
	line-height: 1.25;
	text-shadow: 0 1px 8px rgba(22,18,13,.45);
}
/* The regions tile (6th) is a brand block rather than a photo, so the
   expansion story reads even before we have region photography. */
.sh-tile-brand {
	background: var(--coral);
	display: flex; flex-direction: column; justify-content: flex-end;
	padding: 20px 18px;
}
.sh-tile-brand::after { display: none; }
/* Relative, not static: z-index only applies to a positioned box, and both of
   these have to sit above the hover wash. The base .sh-tile-label sets
   left/right/bottom for its absolute placement, and a relative box would OFFSET
   itself by those, so they are cleared here or the label slides up over the
   kicker. */
.sh-tile-brand .sh-tile-label {
	position: relative;
	left: auto; right: auto; bottom: auto;
	z-index: 2;
	color: var(--maroon-deep);
}
.sh-tile-brand .kicker {
	position: relative; z-index: 2;
	font-family: var(--sh-display);
	font-size: 1.9rem;
	color: var(--maroon-deep);
	line-height: 1.1;
	margin-bottom: 8px;
}

/* ========================================================= PROPERTY CARDS */

.sh-card {
	display: flex; flex-direction: column;
	background: transparent;
	color: var(--ink);
	height: 100%;
}
.sh-card:hover { text-decoration: none; }
.sh-card-media {
	position: relative;
	aspect-ratio: 4 / 3;
	border-radius: var(--r-card);
	overflow: hidden;
	background: var(--stone);
	margin-bottom: var(--space-sm);
	box-shadow: 0 0 0 0 rgba(92,14,7,0);
	/* ROUND 3, fixes 5 and 8: on hover the brand's sculpted corner GROWS on the
	   image's top right, exactly as it does on the live site. The radius is the
	   animated property, so the photograph is reshaped rather than covered. */
	transition: box-shadow .18s ease, border-radius .32s ease;
}
.sh-card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.sh-card:hover .sh-card-media img,
.sh-card:focus-visible .sh-card-media img { transform: scale(1.04); }
/* A visible state on the whole card, not just a nudge on the photograph, so
   the target reads as clickable on hover and on keyboard focus alike. */
.sh-card:hover .sh-card-media,
.sh-card:focus-visible .sh-card-media {
	box-shadow: 0 10px 26px rgba(22,18,13,.14);
	border-radius: var(--r-card) var(--r-hover) var(--r-card) var(--r-card);
}
.sh-card:hover .sh-card-name { color: var(--maroon); }
.sh-card:focus-visible { outline: 3px solid var(--maroon); outline-offset: 4px; border-radius: var(--r-card); }
@media (prefers-reduced-motion: reduce) {
	.sh-card-media { transition: none; }
}

/* Bookmark / save control, top-right of the image, per the Figma card. */
.sh-save {
	position: absolute; top: 12px; right: 12px; z-index: 2;
	width: 40px; height: 40px;
	display: inline-flex; align-items: center; justify-content: center;
	background: rgba(247,245,240,.92);
	border: none;
	border-radius: 50%;
	color: var(--maroon);
}
.sh-save svg { width: 17px; height: 17px; }
.sh-save:hover, .sh-save.is-saved { background: var(--acid); color: var(--cta-ink); }

.sh-card-rating {
	position: absolute; left: 12px; bottom: 12px; z-index: 3;
	background: rgba(247,245,240,.94);
	color: var(--maroon);
	font-size: 0.82rem;
	font-weight: 600;
	padding: 5px 10px;
	border-radius: var(--r-ctl);
}
/* Fix 20: "4.9 (20)". The count sits beside the score in a lighter weight, so
   the score still leads and the sample size is right there with it. */
.sh-card-rating .n { font-weight: 400; color: var(--ink-soft); margin-left: 3px; }

/* ------------------------------------------ card gallery arrows (fix 20)
   Prev / next through the listing's first few photographs, on the RESULTS
   cards only. This is the one place the round deliberately reverses comment
   #187: Fiona asked for click-through on the all-properties cards, while the
   hero and the featured cards stay static. Nothing auto-advances, there is no
   library, and every frame past the first is lazy-loaded. */
.sh-card-media .sh-shot { position: absolute; inset: 0; opacity: 0; transition: opacity .25s ease; }
.sh-card-media .sh-shot.is-on { opacity: 1; }
.sh-gal-btn {
	position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
	width: 34px; height: 34px;
	display: none; align-items: center; justify-content: center;
	background: rgba(247,245,240,.94);
	color: var(--maroon);
	border: none;
	border-radius: 50%;
	font-size: 1rem; line-height: 1;
	box-shadow: 0 2px 10px rgba(22,18,13,.22);
}
.sh-gal-prev { left: 10px; }
.sh-gal-next { right: 10px; }
.sh-card-media:hover .sh-gal-btn,
.sh-card:focus-within .sh-gal-btn { display: inline-flex; }
.sh-gal-btn:hover { background: var(--acid); color: var(--cta-ink); }
.sh-gal-dots {
	position: absolute; left: 0; right: 0; bottom: 10px; z-index: 3;
	display: none; justify-content: center; gap: 5px;
	pointer-events: none;
}
.sh-card-media:hover .sh-gal-dots,
.sh-card:focus-within .sh-gal-dots { display: flex; }
.sh-gal-dots i {
	width: 6px; height: 6px; border-radius: 50%;
	background: rgba(247,245,240,.55);
}
.sh-gal-dots i.is-on { background: var(--acid); }

.sh-card-eyebrow {
	font-family: var(--sh-body);
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--ink-soft);
	margin-bottom: 7px;
}
/* Fix 20: guests / bedrooms / bathrooms as icons plus a number, rather than a
   run of small-caps words. Reads at a glance and survives a narrow card. */
.sh-card-specs {
	display: flex; flex-wrap: wrap; gap: 14px;
	font-family: var(--sh-body);
	font-size: 0.88rem;
	color: var(--ink-soft);
	margin-bottom: 8px;
}
.sh-card-specs span { display: inline-flex; align-items: center; gap: 6px; }
.sh-card-specs svg { width: 17px; height: 17px; flex-shrink: 0; color: var(--maroon); }
.sh-card-name {
	font-family: var(--sh-body);
	font-weight: 600;
	font-size: 1.08rem;
	color: var(--offblack);
	line-height: 1.32;
	margin-bottom: 6px;
	transition: color .16s ease;
}
.sh-card-price { font-size: 0.95rem; color: var(--ink-soft); margin-top: auto; }
.sh-card-price .amount { font-weight: 600; color: var(--maroon); font-size: 1.05rem; }

/* ------------------------------------------- Featured properties, asymmetric */

/* ROUND 3, fix 5. Three rows, every one of them filling the full width evenly:
     row 1   three equal cards
     row 2   ONE full-width wide card
     row 3   two cards plus the acid Browse-all tile
   Six columns, two per item, six for the wide one. No orphan card ending in a
   weird spot, and a real gutter in both directions so no two cards touch. */
.sh-featured {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: var(--sh-gap-row) var(--sh-gap);
}
.sh-featured > * { grid-column: span 2; }
/* The full-width card gets a cinematic ratio: at 1240px a 4:3 frame would be
   930px tall and swallow the page. */
.sh-featured > .span-wide { grid-column: 1 / -1; }
.sh-featured > .span-wide .sh-card-media { aspect-ratio: 21 / 9; }

.sh-browse-tile {
	grid-column: span 2;
	display: flex; flex-direction: column; justify-content: space-between;
	gap: var(--space-md);
	background: var(--acid);
	color: var(--cta-ink);
	border-radius: var(--r-card);
	padding: var(--space-lg) var(--space-md);
	/* Matches the height of the 4:3 image plus the name and price block beside
	   it, so row three sits square rather than one tile floating short. */
	min-height: 100%;
	transition: background .16s ease, box-shadow .18s ease;
}
.sh-browse-tile:hover { background: var(--acid-deep); text-decoration: none; box-shadow: 0 10px 26px rgba(22,18,13,.14); }
.sh-browse-tile:focus-visible { outline: 3px solid var(--maroon); outline-offset: 3px; }
.sh-browse-tile .t {
	font-family: var(--sh-display);
	font-size: 2rem;
	color: var(--cta-ink);
	line-height: 1.08;
}
.sh-browse-tile .go { font-weight: 600; font-size: 0.95rem; }

/* Plain grids (results, collections, related). */
.sh-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
	gap: var(--sh-gap-row) var(--sh-gap);
}

/* ============================================================== STAY TYPES */

/* ROUND 3, fix 6. The judgement call Fiona left open was 2x2 versus a row of
   four. Four across, with a real gutter and a slightly taller frame, is what
   this page can afford: 2x2 on a 1240px page makes each tile ~600px square and
   turns four small signposts into 1,250px of scrolling for no extra
   information. The gap and the left-aligned heading are the parts of the note
   that were actually about the problem, and both are applied. */
/* ROUND 6, Fiona's fix 7: "this is the only section I can see that is missing a
   curve", corrected 30 Sep to TOP-RIGHT ("the curve here should be top right
   not top left"). The light orange sweeps up into the section above it on the
   right hand side, directly under the hero's own bottom-right sweep, so the
   two read as one continuous right hand edge down the page.

   The band has to own the radius and the background together, which is why the
   rule is on the section and not on .sh-band-warm: only this instance curves. */
.sh-section.sh-band-warm.sh-types {
	border-radius: 0 var(--r-hero) 0 0;
}
.sh-type-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--sh-gap-row) var(--sh-gap);
}
.sh-type-tile {
	position: relative;
	display: block;
	aspect-ratio: 3 / 4;
	border-radius: var(--r-card);
	overflow: hidden;
	background: var(--lorange-deep);
}
.sh-type-tile { transition: box-shadow .18s ease; }
.sh-type-tile img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.sh-type-tile:hover img,
.sh-type-tile:focus-visible img { transform: scale(1.05); }
.sh-type-tile:hover { box-shadow: 0 10px 26px rgba(22,18,13,.16); }
.sh-type-tile:focus-visible { outline: 3px solid var(--maroon); outline-offset: 3px; }
/* #189: enough of a foot-of-frame gradient that the serif label is legible on
   a bright photograph, without a flat wash that hides the room itself. */
.sh-type-tile::after {
	content: "";
	position: absolute; inset: 0;
	background: linear-gradient(180deg, rgba(22,18,13,0) 42%, rgba(22,18,13,.34) 68%, rgba(22,18,13,.80) 100%);
}
.sh-type-label {
	position: absolute; left: 20px; right: 20px; bottom: 18px; z-index: 2;
	font-family: var(--sh-display);
	font-size: 1.45rem;
	line-height: 1.15;
	color: #FFF9F4;
	text-shadow: 0 1px 10px rgba(22,18,13,.5);
}

/* ================================================================= REVIEWS */

/* Fix 7: real air between the review cards, and more of it inside them. The
   eyebrow above the heading is gone (see the reviews shortcode). */
.sh-reviews {
	display: flex;
	gap: var(--sh-gap);
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	padding-bottom: 14px;
	scrollbar-width: thin;
}
.sh-review {
	flex: 0 0 clamp(280px, 34vw, 400px);
	scroll-snap-align: start;
	background: var(--white);
	border-radius: var(--r-card);
	padding: var(--space-lg);
	display: flex; flex-direction: column; gap: var(--space-sm);
}
.sh-review-head { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
.sh-review-name { font-weight: 600; color: var(--offblack); }
.sh-review-name .chan {
	font-weight: 400;
	font-size: 0.8rem;
	color: var(--ink-soft);
	margin-left: 6px;
}
.sh-review-date { font-size: 0.82rem; color: var(--ink-soft); white-space: nowrap; }
.sh-stars { color: var(--coral); letter-spacing: 2px; font-size: 0.95rem; }
.sh-review-text { font-size: 0.98rem; margin: 0; }

.sh-carousel-nav { display: flex; gap: 10px; margin-top: var(--space-md); justify-content: center; }
.sh-carousel-nav button {
	width: 46px; height: 46px;
	border-radius: 50%;
	border: 1.5px solid var(--maroon);
	background: transparent;
	color: var(--maroon);
	font-size: 1.1rem;
}
.sh-carousel-nav button:hover { background: var(--maroon); color: #FFF6F1; }
.sh-carousel-nav button[disabled] { opacity: .35; cursor: not-allowed; }

/* ========================================================== TRAVEL GUIDES */

.sh-post-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--sh-gap-row) var(--sh-gap);
}
.sh-post-card {
	display: flex; flex-direction: column;
	background: var(--white);
	border-radius: var(--r-card);
	overflow: hidden;
	color: var(--ink);
}
.sh-post-card { transition: box-shadow .18s ease, border-radius .32s ease; }
.sh-post-card:hover { text-decoration: none; box-shadow: 0 10px 26px rgba(22,18,13,.12); }
.sh-post-card:focus-visible { outline: 3px solid var(--maroon); outline-offset: 3px; }
.sh-post-card:hover h3 { color: var(--maroon-deep); }
.sh-post-media {
	aspect-ratio: 16 / 10;
	background: var(--lorange);
	overflow: hidden;
	/* Fix 8: the same top-right corner grows on a guide card's image. */
	transition: border-radius .32s ease;
}
.sh-post-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
/* The card clips its children, so the corner is grown on the card itself and
   the image frame follows it. That way the curve cuts against the page rather
   than showing a white notch inside a white card. */
.sh-post-card:hover,
.sh-post-card:focus-visible { border-radius: var(--r-card) var(--r-hover) var(--r-card) var(--r-card); }
.sh-post-card:hover .sh-post-media,
.sh-post-card:focus-visible .sh-post-media { border-radius: 0 var(--r-hover) 0 0; }
.sh-post-card:hover .sh-post-media img,
.sh-post-card:focus-visible .sh-post-media img { transform: scale(1.04); }
.sh-post-body { padding: var(--space-lg) var(--space-lg) var(--space-xl); display: flex; flex-direction: column; gap: 12px; flex: 1; }
.sh-post-body h3 { margin: 0; font-size: 1.35rem; }
.sh-post-body p { font-size: 0.97rem; margin: 0; }
.sh-post-body .read {
	margin-top: auto; padding-top: 14px;
	font-weight: 600; font-size: 0.93rem; color: var(--maroon);
}

/* ========================================================= SPLIT CTA BLOCK */

.sh-split {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--space-2xl);
	align-items: center;
}
.sh-split-media {
	border-radius: var(--r-card);
	overflow: hidden;
	aspect-ratio: 4 / 3;
	background: var(--lorange-deep);
}
.sh-split-media img { width: 100%; height: 100%; object-fit: cover; }
.sh-split-copy h2 { margin-bottom: var(--space-sm); }

/* ------------------------------------------------- Find your ideal stay
   ROUND 5, fix 2. Measured off booking-site-rebuild/examples/
   figma-find-ideal-stay.png (1200px export of the 1440px frame):

     band                 390 tall (32.5vw), light orange, capped at 460
     photograph           x 0 to 593 (49.4%), y 0 to 390: flush to the band's
                          top, bottom and left edges, no band under it
     arched corner        top right only, a quarter round of 165 (13.75vw)
     copy                 starts 66px (5.5vw) right of the photograph,
                          vertically centred, about 440 wide
     heading              The Seasons 50px (4.17vw) -> 60 at 1440, maroon
     paragraph            Matter 18px (1.5vw) on 1.3, MAROON not body grey
     button               the site's acid pill, 24 under the paragraph

   The band itself is the grid, so nothing pads the photograph off an edge. The
   copy column's right padding is the same sum .sh-wrap produces (half the
   spare width plus the wrap padding), so the text still ends on the page's
   right-hand content edge. */
.sh-ideal {
	--sh-ideal-r: clamp(84px, 13.75vw, 198px);
	display: grid;
	grid-template-columns: minmax(0, 49.4%) minmax(0, 1fr);
	min-height: clamp(340px, 32.5vw, 460px);
	background: var(--lorange);
}
.sh-ideal-media {
	position: relative;
	overflow: hidden;
	border-radius: 0 var(--sh-ideal-r) 0 0;
	background: var(--lorange-deep);
	min-height: 100%;
}
.sh-ideal-media img {
	position: absolute; inset: 0;
	width: 100%; height: 100%;
	object-fit: cover;
}
.sh-ideal-copy {
	align-self: center;
	padding: var(--space-2xl) max(var(--wrap-pad), calc((100vw - var(--wrap)) / 2 + var(--wrap-pad))) var(--space-2xl) clamp(32px, 5.5vw, 80px);
}
.sh-ideal-copy > * { max-width: 540px; }
/* About 440px of text in the 1200 export (37vw), so five short lines rather
   than three long ones. */
.sh-ideal-copy p { max-width: min(540px, 37vw); }
.sh-ideal-copy h2 {
	font-size: clamp(2.1rem, 4.17vw, 3.75rem);
	letter-spacing: 0;
	margin-bottom: clamp(16px, 1.7vw, 24px);
}
.sh-ideal-copy p {
	font-size: clamp(17px, 1.5vw, 21.6px);
	line-height: 1.32;
	color: var(--maroon);
	margin: 0;
}
.sh-ideal-copy .sh-ideal-cta { margin-top: clamp(20px, 2vw, 30px); }

/* ============================================================ SIGN UP BAND */

/* ROUND 5: the Sign up & save band is part of the footer now, and styled with
   it in base.css (.sh-signup-band). The [stayhub_signup] shortcode renders
   nothing, so there is no page-level band left to style here. */

/* ============================================================ TRUST STRIP */

.sh-trust {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--sh-gap);
	background: var(--lorange);
	border-radius: var(--r-card);
	padding: var(--space-lg);
}
.sh-trust-item { display: flex; gap: 14px; align-items: flex-start; }
.sh-trust-item .ico {
	flex-shrink: 0;
	width: 40px; height: 40px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: 50%;
	background: var(--maroon);
	color: var(--lorange);
	font-size: 1rem;
}
.sh-trust-item strong { display: block; color: var(--maroon); font-weight: 600; }
.sh-trust-item span.sub { font-size: 0.9rem; color: var(--ink-soft); }

/* ============================================================ VALUE PROPS */

.sh-value-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sh-gap); }
.sh-value-item {
	background: var(--white);
	border-radius: var(--r-card);
	padding: var(--space-lg);
}
.sh-value-item .ico {
	width: 52px; height: 52px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: 50%;
	background: var(--lorange);
	color: var(--maroon);
	font-size: 1.2rem;
	margin-bottom: 18px;
}
.sh-value-item h3 { font-size: 1.3rem; margin-bottom: var(--space-xs); }

/* Book-direct benefit checkmarks (Stayhub Difference page). */
.sh-checks { display: flex; flex-direction: column; gap: 18px; margin: 0 0 30px; padding: 0; list-style: none; }
.sh-checks li { display: flex; gap: 14px; align-items: flex-start; }
.sh-checks .tick {
	flex-shrink: 0;
	width: 30px; height: 30px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: 50%;
	background: var(--acid);
	color: var(--cta-ink);
	font-weight: 600;
	font-size: 0.9rem;
}
.sh-checks strong { color: var(--maroon); }

/* =================================================================== FAQS */

.sh-faq-list { display: flex; flex-direction: column; gap: 0; }
.sh-faq-item { border-bottom: 1px solid var(--line); }
.sh-faq-item summary {
	cursor: pointer;
	list-style: none;
	padding: 22px 44px 22px 0;
	position: relative;
	font-family: var(--sh-body);
	font-weight: 600;
	font-size: 1.05rem;
	color: var(--maroon);
}
.sh-faq-item summary::-webkit-details-marker { display: none; }
.sh-faq-item summary::after {
	content: "+";
	position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
	font-size: 1.5rem; color: var(--coral); line-height: 1;
}
.sh-faq-item[open] summary::after { content: "\2013"; }
.sh-faq-a { padding: 0 44px 24px 0; font-size: 1rem; }

/* ================================================== FILTER BAR + RESULTS */

.sh-filter-bar {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: var(--space-xs);
	background: var(--lorange);
	border-radius: var(--r-card);
	padding: var(--space-md);
	margin-bottom: var(--space-md);
}
.sh-results-head {
	display: flex; justify-content: space-between; align-items: center;
	gap: var(--space-sm); flex-wrap: wrap;
	margin-bottom: var(--space-md);
}
.sh-results-count { font-weight: 600; color: var(--maroon); }
.sh-sort { max-width: 250px; }

/* ==================================== ALL PROPERTIES: band, map, results
   ROUND 3, fixes 18 to 21. The page is now the shape of the live site: a
   maroon search band pinned to the top of the window, the results as two-up
   cards on the left, and the map on the right with a dot per property. */

/* A wider container than the rest of the site: a map and a two-up card column
   side by side need the room, and this is the only page that gets it. */
.sh-wrap-wide {
	max-width: 1640px;
	padding-left: var(--wrap-pad-wide);
	padding-right: var(--wrap-pad-wide);
}

/* ------------------------------------------------------- the sticky band
   ROUND 4, fix 4: mid orange #EB7B5C, not maroon ("the maroon looks a bit
   dated"). The text on it is MAROON rather than white, and that is a contrast
   decision rather than a taste one: white on #EB7B5C measures 2.8:1, which
   fails AA for anything at this size, while maroon #5C0E07 on the same coral
   measures 4.9:1 and passes. So every label, count and control on the band is
   maroon, and white is not used on the coral at all. */
.sh-filter-band {
	position: sticky;
	top: 84px;                     /* directly under the sticky site header */
	z-index: 50;
	background: var(--coral);
	color: var(--maroon);
	box-shadow: 0 10px 24px rgba(22,18,13,.14);
}
.sh-filter-band-inner {
	display: flex; align-items: flex-end; gap: var(--space-sm);
	padding: 14px var(--wrap-pad-wide);
	max-width: 1640px; margin: 0 auto;
}
/* Scoped to the band's own row, NOT to `.sh-filter-band .sh-field`. The drawer
   is inside the band too, and once the drawer became a column (round 4, fix 3)
   a flex-basis of 190px stopped meaning "190px wide" and started meaning
   "190px tall", which gave every filter in the panel a 190px slab of its own. */
.sh-filter-band-inner .sh-field { min-width: 0; flex: 0 1 190px; }
.sh-filter-band label { color: var(--maroon); }
.sh-filter-band input,
.sh-filter-band select {
	background-color: #FFF9F4;
	border-color: #FFF9F4;
	color: var(--maroon);
	border-radius: var(--r-pill);
	padding-left: 20px; padding-right: 20px;
}
.sh-filter-band select {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%235C0E07' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 18px center;
	background-size: 12px 8px;
	padding-right: 42px;
}
.sh-filter-band input[type="date"] { color-scheme: light; }
.sh-band-spacer { flex: 1 1 auto; }
.sh-band-count { font-size: 0.92rem; font-weight: 600; color: var(--maroon); white-space: nowrap; padding-bottom: 13px; }

/* ROUND 4, fix 3. On the old maroon band these were outline pills in white,
   and on the new coral that treatment vanished into the background: a
   translucent white edge on #EB7B5C is barely a shape. They are solid now, a
   near-white pill with a maroon edge and maroon type, so the two controls on
   the band read as controls at a glance. Open, Filters inverts to solid maroon
   rather than acid: acid on coral is two bright warm tones fighting, while
   maroon is the same relationship as everything else on the band. */
.sh-band-btn {
	display: inline-flex; align-items: center; gap: 8px;
	font-family: var(--sh-body); font-weight: 600; font-size: 0.95rem;
	background: #FFF9F4;
	color: var(--maroon);
	border: 1.5px solid var(--maroon);
	border-radius: var(--r-pill);
	padding: 13px 22px;
	white-space: nowrap;
	transition: background .16s ease, color .16s ease, border-color .16s ease;
}
.sh-band-btn:hover { background: var(--maroon); color: #FFF6F1; }
.sh-band-btn[aria-expanded="true"],
.sh-band-btn[aria-pressed="true"] { background: var(--maroon); border-color: var(--maroon); color: #FFF6F1; }
.sh-band-btn .tag {
	background: var(--maroon); color: #FFF6F1;
	border-radius: var(--r-pill); font-size: 0.74rem; font-weight: 600; padding: 1px 8px;
}
.sh-band-btn[aria-expanded="true"] .tag,
.sh-band-btn[aria-pressed="true"] .tag { background: var(--acid); color: var(--cta-ink); }

/* ------------------------------------------------------- the Filters drawer
   ROUND 4, fix 3: a stacked COLUMN on a light orange panel, not a row of five
   selects on a dark slab. Each control is a readable width with its label above
   it, the two groups say what they are for, and clearing is its own step at the
   foot of the panel. */
/* AN ANCHORED DROPDOWN, not a full-width band panel (Fiona, 1 Oct 2026).

   As a band panel it ran the width of the page and was taller than the
   viewport, so opening Filters replaced the screen and the only way back was
   to scroll up and find the button again. It is now a normal dropdown: about
   380px, hung under the Filters button on fixed coordinates (the band is
   sticky, so the button does not move), with its own head and a close.

   Fixed rather than absolute for the same reason as the date picker: it then
   does not matter what any ancestor does with overflow. */
.sh-filter-drawer {
	position: fixed;
	z-index: 200;
	width: min(380px, calc(100vw - 24px));
	background: var(--lorange);
	border-radius: var(--r-card);
	box-shadow: 0 24px 60px rgba(22,18,13,.26);
	display: flex;
	flex-direction: column;
	max-height: min(70vh, 620px);
	overflow: hidden;
}
.sh-filter-drawer[hidden] { display: none; }
.sh-filter-drawer-head {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--space-sm);
	padding: 12px 16px;
	border-bottom: 1px solid rgba(92,14,7,.16);
	flex: 0 0 auto;
}
.sh-filter-drawer-title {
	font-family: var(--sh-body);
	font-weight: 600;
	font-size: 0.78rem;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--maroon);
}
.sh-drawer-close {
	width: 34px; height: 34px;
	display: inline-flex; align-items: center; justify-content: center;
	border: 0; border-radius: 50%;
	background: transparent;
	color: var(--maroon);
	font-size: 1rem; line-height: 1;
	cursor: pointer;
}
.sh-drawer-close:hover { background: rgba(92,14,7,.10); }
.sh-filter-drawer-inner {
	max-width: none;
	padding: var(--space-md) 16px;
	display: flex; flex-direction: column; gap: var(--space-md);
	/* The body scrolls; the head and the actions below stay put. */
	flex: 1 1 auto;
	overflow-y: auto;
	overscroll-behavior: contain;
}
.sh-filter-group { display: flex; flex-direction: column; gap: var(--space-sm); }
.sh-filter-group-title {
	font-family: var(--sh-body);
	font-size: 0.76rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: #A34527;
}
.sh-filter-drawer label { color: var(--maroon); }
.sh-filter-drawer input,
.sh-filter-drawer select {
	background-color: var(--white); border-color: var(--white); color: var(--maroon);
	border-radius: var(--r-pill); padding-left: 20px; padding-right: 42px;
}
.sh-filter-drawer .sh-drawer-actions {
	display: flex; gap: var(--space-sm); align-items: center; flex-wrap: wrap;
	border-top: 1px solid rgba(92,14,7,.16);
	padding-top: var(--space-md);
	/* Pinned to the foot of the panel so Clear filters is always reachable,
	   however far down the list you have scrolled. The shadow is what makes it
	   read as a bar the content passes behind rather than as a row that has
	   somehow jumped out of order. */
	margin-top: auto;
	position: sticky;
	bottom: calc(var(--space-md) * -1);
	background: var(--lorange);
	padding-bottom: var(--space-md);
	box-shadow: 0 -10px 16px -10px rgba(92,14,7,.28);
}
/* Clear filters is the one destructive control in the panel, so it is a real
   button with an edge and a mark on it rather than a line of text. */
.sh-drawer-clear {
	display: inline-flex; align-items: center; gap: 9px;
	font-family: var(--sh-body); font-weight: 600; font-size: 0.95rem;
	background: var(--white);
	color: var(--maroon);
	border: 1.5px solid var(--maroon);
	border-radius: var(--r-pill);
	padding: 12px 24px;
	min-height: 46px;
	transition: background .16s ease, color .16s ease;
}
.sh-drawer-clear:hover { background: var(--maroon); color: #FFF6F1; }
.sh-drawer-clear span { font-size: 0.82em; }
.sh-drawer-hint { font-size: 0.88rem; color: #8A4630; }

/* ------------------------------------------------------- results and map */
.sh-results-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 42%;
	gap: var(--space-xl);
	align-items: start;
}
.sh-results-col { min-width: 0; }
/* Two-up cards beside the map, as on the live site. */
.sh-results-col .sh-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Fix 20: on this page a card is a distinct, highlighted box rather than a
   bare image with text under it. */
/* ROUND 5, fix 3: no outline. The box is its white surface and the resting
   card shadow; on hover (or when its pin is hovered on the map) it lifts, and
   the sculpted corner grows, instead of a stroke changing colour. */
/* Two classes, not one: the card is an <a>, and Elementor's frontend carries
   `.elementor a { box-shadow: none }` at (0,1,1), which silently removed a
   single-class shadow on every linked card. */
.sh-card.sh-card-boxed {
	background: var(--white);
	border-radius: var(--r-card);
	padding: var(--space-xs);
	box-shadow: var(--sh-shadow-card);
	transition: box-shadow .18s ease, border-radius .32s ease, transform .18s ease;
}
.sh-card-boxed .sh-card-media { margin-bottom: var(--space-xs); }
.sh-card-boxed .sh-card-body { padding: 4px 10px 10px; }
.sh-card-boxed:hover,
.sh-card-boxed.is-hi {
	box-shadow: var(--sh-shadow-lift);
	border-radius: var(--r-card) var(--r-hover) var(--r-card) var(--r-card);
}
/* The image inside a boxed card already has its own corner, and the lift is on
   the box, so the image does not throw a second shadow inside it. */
.sh-card-boxed:hover .sh-card-media,
.sh-card-boxed.is-hi .sh-card-media { box-shadow: none; }

/* The map column: pinned beside the results, its own height, its own scroll. */
.sh-map-col {
	position: sticky;
	top: 168px;                       /* header 84 + band 84 */
	height: calc(100vh - 188px);
	min-height: 460px;
	border-radius: var(--r-card);
	overflow: hidden;
	box-shadow: var(--sh-shadow-card);   /* round 5, fix 3: was a 1px stroke */
	background: var(--stone);
}
.sh-map-canvas { width: 100%; height: 100%; }
/* ROUND 4, fix 2. Applied only while the map is on plain OpenStreetMap tiles,
   which is what it falls back to until a CARTO key is set (see the tile layer
   in the plugin's app.js). Desaturated and lifted, the standard style's
   contour, ferry route and reserve linework drops back to a whisper and the
   maroon price pins carry the map on their own.

   It has to be a `filter` on the tile pane, and it cannot be a wash layer over
   the map: everything Leaflet draws, tiles and pins alike, lives inside
   .leaflet-map-pane, which carries a transform and is therefore its own
   stacking context at z-index 400. Nothing sitting outside it can be slipped
   between the tiles and the pins, so a wash either sits under the whole map or
   over the pins and drains them too. Filtering the tile pane leaves the marker
   pane above it untouched, which is what keeps the pins in full maroon. */
.sh-map-muted .leaflet-tile-pane {
	filter: saturate(0.2) brightness(1.05) contrast(0.92);
}
/* NOTE for whoever looks at this next: on a 2x display the map shows a faint
   grid of hairlines on the tile boundaries, most visible over water at the
   country-wide zoom. It is NOT the muting. It renders identically with the
   filter switched off, it was there on the OSM tiles before round 4, and
   overlapping the tiles by a pixel does not shift it, so it is a Leaflet
   rasterisation artifact rather than a gap. Left alone here: it is out of
   round 4's scope and it wants its own look. */
.sh-map-note {
	position: absolute; left: 12px; top: 12px; z-index: 500;
	background: rgba(247,245,240,.95);
	color: var(--maroon);
	font-size: 0.82rem; font-weight: 600;
	padding: 8px 14px;
	border-radius: var(--r-pill);
	box-shadow: 0 2px 10px rgba(22,18,13,.16);
	display: flex; align-items: center; gap: 8px;
}
.sh-map-note input { width: auto; min-height: 0; margin: 0; accent-color: var(--maroon); }
.sh-map-note label { margin: 0; text-transform: none; letter-spacing: 0; font-size: 0.82rem; color: var(--maroon); }

/* Property dots. Drawn in CSS rather than as marker images, so they are brand
   coloured and the price fits inside them. */
.sh-pin {
	background: var(--maroon);
	color: #FFF6F1;
	font-family: var(--sh-body);
	font-weight: 600;
	font-size: 0.78rem;
	line-height: 1;
	padding: 7px 11px;
	border-radius: var(--r-pill);
	border: 2px solid #FFF9F4;
	box-shadow: 0 2px 8px rgba(22,18,13,.34);
	white-space: nowrap;
	text-align: center;
}
.sh-pin.is-hi { background: var(--acid); color: var(--cta-ink); border-color: var(--maroon); }
/* A SUGGESTION pin: on the map, but visibly not one of the matches.
   Reversed out rather than merely faded, so it still reads cleanly against
   the map at any zoom while the real results keep the solid maroon. Hover
   brings it up to full strength, because it is still a real property you can
   click. (Fiona, 1 Oct 2026: the map should show the broader listings too.) */
.sh-pin.is-soft {
	background: #FFF9F4;
	color: var(--maroon);
	border-color: var(--coral);
	box-shadow: 0 2px 6px rgba(22,18,13,.20);
	opacity: .92;
}
.sh-pin.is-soft:hover { background: var(--coral); color: var(--maroon); opacity: 1; }
.sh-pin.is-soft.is-hi { background: var(--acid); color: var(--cta-ink); border-color: var(--maroon); opacity: 1; }
.leaflet-container { font-family: var(--sh-body); background: var(--stone); }
.leaflet-container a { color: var(--maroon); }
/* The theme's global `img { max-width:100%; height:auto }` reset would fight
   Leaflet's absolutely positioned tiles, so the map's own images opt out.
   Leaflet ships !important guards for most of these; this covers the rest and
   makes the intent visible rather than relying on a vendor file. */
.leaflet-container img,
.leaflet-container .leaflet-tile { max-width: none; height: auto; }
.leaflet-popup-content { font-size: 0.9rem; line-height: 1.45; margin: 14px 18px; }
.leaflet-popup-content strong { color: var(--maroon); }
.leaflet-popup-content-wrapper { border-radius: var(--r-card); }

/* ------------------------------------------- map popup with a photograph
   1 Oct 2026, Fiona: "when you click on an item in the map I would love for
   the main image to be included in the preview". A pin carrying only a price
   and a name makes you click through just to see whether you like the look of
   the place; with the picture in it the map is browsable on its own.

   Leaflet pads .leaflet-popup-content, which would leave a white margin round
   a full-bleed image, so the padding is removed here and the body puts it back
   on the text only. */
/* Leaflet writes the content width inline from maxWidth, so this must restate
   a width rather than say auto: auto collapses the popup to the width of the
   longest unbreakable word, which turned "Boutique City Apartment" into three
   lines in a sliver. */
.sh-map-popup .leaflet-popup-content { margin: 0; width: 232px !important; }
.sh-map-popup .leaflet-popup-content-wrapper { padding: 0; overflow: hidden; }
.sh-map-pop { display: block; color: inherit; }
.sh-map-pop:hover { text-decoration: none; }
.sh-map-pop-img {
	width: 100%;
	aspect-ratio: 16 / 10;
	object-fit: cover;
	display: block;
	background: var(--lorange);
}
.sh-map-pop-body { display: block; padding: 12px 14px 4px; }
.sh-map-pop-name {
	display: block;
	font-family: var(--sh-display);
	font-size: 1.02rem;
	line-height: 1.2;
	color: var(--maroon);
}
.sh-map-pop-meta { display: block; margin-top: 3px; font-size: 0.86rem; color: var(--ink-soft); }
.sh-map-pop-go {
	display: block; margin-top: 8px;
	font-size: 0.86rem; font-weight: 600; color: var(--maroon);
	border-bottom: 2px solid var(--coral);
	width: fit-content;
}
.sh-map-pop:hover .sh-map-pop-go { border-bottom-color: var(--maroon); }
.sh-map-pop-note {
	display: block;
	padding: 6px 14px 12px;
	font-size: 0.76rem;
	color: var(--ink-soft);
}

.sh-bp-nights {
	margin: 8px 0 0;
	font-size: 0.9rem;
	font-weight: 600;
	color: var(--coral-ink, #B8452A);
}
.sh-bp-nights:empty { display: none; }

/* ------------------------------------------------- empty state with alternatives
   When a search comes back with nothing, the page offers the stays the guest
   COULD have rather than apologising. The heading spans the whole grid so the
   alternatives read as their own section rather than as more results, and the
   cards themselves are visibly a suggestion: slightly held back, and lifting
   on hover like anything else you can click. */
.sh-alt-head {
	grid-column: 1 / -1;
	margin-top: var(--space-md);
	padding-top: var(--space-md);
	border-top: 1px solid var(--line);
}
/* The first section follows the explanation directly, so it does not need a
   rule above it as well. */
.sh-alt-head:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.sh-alt-head h3 { margin: 0 0 4px; font-size: 1.25rem; }
.sh-alt-head p { margin: 0; color: var(--ink-soft); font-size: 0.95rem; }
.sh-card.is-alt { opacity: .88; transition: opacity .18s ease, box-shadow .18s ease; }
.sh-card.is-alt:hover { opacity: 1; }
.sh-empty-actions { margin-top: var(--space-md); display: flex; gap: var(--space-sm); flex-wrap: wrap; justify-content: center; }
.sh-empty-actions:empty { display: none; }

/* SHORTER than a standard empty state (Fiona, 1 Oct 2026). This one is not a
   dead end: there are recommendations directly underneath it, and at full
   height it pushed every one of them below the fold, so the page looked like
   it had nothing to offer. Tighter padding and a smaller heading buy back
   enough room for the first suggestions to show. */
#empty-state { padding: var(--space-lg) var(--space-md); }
#empty-state h3 { font-size: clamp(1.4rem, 2.2vw, 1.75rem); margin-bottom: 6px; }
#empty-state p { margin-bottom: 0; font-size: 0.98rem; }
#empty-state .sh-empty-actions { margin-top: var(--space-sm); }

/* ============================================ SHARED DATE RANGE PICKER
   One control for both dates, two months at a time, used by the hero bar and
   the results band. Replaced two native <input type="date"> pairs: separate
   one-month pickers that never showed the arrival and the departure together
   and never said how many nights had been chosen.

   The popover is absolutely positioned out of the bar so it is not clipped by
   the bar's own overflow, and it is right-aligned on the results band where
   the control sits near the left edge. */
[data-sh-range] { position: relative; }
.sh-range-btn {
	width: 100%;
	text-align: left;
	background: transparent;
	border: 0;
	font: inherit;
	color: var(--maroon);
	cursor: pointer;
	padding: 0;
	min-height: 24px;
}
.sh-seg .sh-range-btn { padding: 0 20px; height: 58px; }
/* THE NIGHT COUNT IS A PILL.
   It was small coral-ink text sitting directly on the mid-orange results band,
   which is close to unreadable (Fiona, 1 Oct 2026), and it wrapped under the
   dates at awkward moments. A white pill lifts it off the band whatever colour
   the band is, gives it a fixed shape so the control stops changing height as
   you pick, and reads at a glance as "this is the length of your stay" rather
   than as a third date.

   The two parts sit on one baseline and the dates get to shrink first, so a
   long range never pushes the pill onto its own line. */
.sh-range-btn {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: nowrap;
	overflow: hidden;
}
.sh-range-btn .d {
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-weight: 600;
}
.sh-range-btn .n {
	flex: 0 0 auto;
	background: var(--white);
	color: var(--maroon);
	border-radius: var(--r-pill);
	padding: 3px 10px;
	font-size: 0.78rem;
	font-weight: 600;
	line-height: 1.4;
	white-space: nowrap;
}
/* "Add departure" is a prompt, not a fact, so it is outlined rather than solid
   and does not pretend to be a result. */
.sh-range-btn .n-ask {
	background: transparent;
	border: 1px dashed currentColor;
	color: inherit;
	opacity: .85;
}
.sh-range-pop {
	/* FIXED and on <body>: the hero and the search bar both clip their
	   children, so a popover inside either is invisible. */
	position: fixed;
	z-index: 200;
	/* A column, so that when the height is capped to the room below the
	   control it is the MONTHS that scroll and Done stays reachable. */
	display: flex;
	flex-direction: column;
	background: var(--white);
	border-radius: var(--r-card);
	box-shadow: 0 24px 60px rgba(22,18,13,.22);
	padding: var(--space-md);
	width: max-content;
	max-width: min(620px, 92vw);
}
.sh-range-head {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--space-sm);
	margin-bottom: var(--space-sm);
}
.sh-range-label { font-weight: 600; color: var(--maroon); font-size: 0.95rem; }
.sh-range-nav {
	width: 34px; height: 34px;
	border-radius: 50%;
	border: 1px solid var(--line);
	background: var(--white);
	color: var(--maroon);
	cursor: pointer;
	font-size: 1.1rem; line-height: 1;
}
.sh-range-nav:disabled { opacity: .35; cursor: default; }
.sh-range-months { display: flex; gap: var(--space-lg); overflow-y: auto; overscroll-behavior: contain; }
.sh-range-month { min-width: 232px; }
.sh-range-month h4 { margin: 0 0 8px; font-size: 1rem; text-align: center; }
.sh-range-month .dow,
.sh-range-month .days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.sh-range-month .dow span {
	text-align: center; font-size: 0.68rem; font-weight: 600;
	letter-spacing: .06em; text-transform: uppercase; color: var(--ink-soft);
	padding-bottom: 4px;
}
.sh-range-month .day {
	aspect-ratio: 1 / 1;
	display: flex; align-items: center; justify-content: center;
	border: 0; background: transparent;
	font: inherit; font-size: 0.9rem;
	color: var(--maroon);
	border-radius: var(--r-ctl);
	cursor: pointer;
}
.sh-range-month .day.empty { visibility: hidden; }
.sh-range-month .day.past { color: var(--ink-soft); opacity: .4; cursor: default; }
.sh-range-month .day.pick:hover { background: var(--lorange); }
/* The arrival stays lit the whole time the departure is being chosen, and the
   nights between fill in live. This is the part that was missing. */
.sh-range-month .day.in-range { background: var(--lorange); border-radius: 0; }
.sh-range-month .day.sel-in,
.sh-range-month .day.sel-out {
	background: var(--maroon);
	color: #fff;
	font-weight: 600;
}
.sh-range-month .day.sel-in { border-radius: var(--r-ctl) 0 0 var(--r-ctl); }
.sh-range-month .day.sel-out { border-radius: 0 var(--r-ctl) var(--r-ctl) 0; }
.sh-range-foot {
	flex: 0 0 auto;
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--space-md);
	margin-top: var(--space-md);
	padding-top: var(--space-sm);
	border-top: 1px solid var(--line);
	font-size: 0.92rem;
	color: var(--ink);
}
.sh-range-actions { display: flex; align-items: center; gap: var(--space-sm); }
.sh-range-clear {
	background: none; border: 0; font: inherit; cursor: pointer;
	color: var(--maroon); text-decoration: underline;
}
.sh-range-done { padding: 8px 20px; }
/* Scoped to the band, because .sh-filter-band-inner .sh-field is (0,2,0) and
   pins every field to a 190px basis with min-width 0. At 190px the date range
   was being cut off mid-date by its own ellipsis, which is worse than not
   showing it. The dates are the longest thing in the band, so they get the
   room and everything else keeps its 190. */
.sh-filter-band-inner .sh-field-range { flex: 1 1 300px; min-width: 260px; }

/* ----------------------------------------------------- checking availability
   The Hostaway availability call costs about ten seconds on a date range
   nobody has searched recently. A dimmed grid on its own reads as a broken
   page over that long (Fiona, 1 Oct 2026), so the dim is now accompanied by a
   panel that says what is happening and that the first one is the slow one.

   The panel sits over the grid rather than replacing it, so the page does not
   collapse and jump when the answer arrives. */
.sh-results-col { position: relative; }
.sh-results-col .sh-grid.is-checking,
.sh-grid.is-checking { opacity: .3; pointer-events: none; transition: opacity .15s ease; }

.sh-loading {
	position: absolute;
	inset: 0 0 auto 0;
	z-index: 5;
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 10px;
	padding: var(--space-2xl) var(--space-md);
	background: linear-gradient(var(--cream) 62%, rgba(247,245,240,0));
	border-radius: var(--r-card);
}
.sh-loading[hidden] { display: none; }
.sh-loading-main { margin: 0; font-weight: 600; color: var(--maroon); }
.sh-loading-sub { margin: 0; font-size: 0.9rem; color: var(--ink-soft); max-width: 42ch; }

.sh-spinner {
	width: 34px; height: 34px;
	border-radius: 50%;
	border: 3px solid var(--lorange);
	border-top-color: var(--coral);
	animation: sh-spin .8s linear infinite;
}
@keyframes sh-spin { to { transform: rotate(360deg); } }

/* Anyone who has asked for less motion gets a pulse instead of a spin: still
   obviously "working", with nothing rotating. */
@media (prefers-reduced-motion: reduce) {
	.sh-spinner {
		animation: sh-pulse 1.4s ease-in-out infinite;
		border-top-color: var(--coral);
	}
	@keyframes sh-pulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
}

/* ------------------------------------------------ search by property name
   Lives in the Filters drawer, not the hero (Fiona, 1 Oct 2026): in here the
   label can be exact about matching names only, so nobody types a suburb into
   it expecting the homes in that suburb. */
.sh-filter-group .sh-field input[type="search"] { width: 100%; }
.sh-field-hint {
	display: block;
	margin-top: 6px;
	font-size: 0.82rem;
	color: var(--ink-soft);
}
.leaflet-bar a { color: var(--maroon); }

/* The mobile map toggle. Hidden on desktop, where the map is always there. */
.sh-map-toggle { display: none; }

/* Filter chips (Things to do sub pages). */
.sh-chips { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: var(--space-lg); }
.sh-chip {
	font-family: var(--sh-body);
	font-size: 0.92rem;
	font-weight: 600;
	padding: 10px 18px;
	border-radius: var(--r-ctl);
	border: 1.5px solid var(--maroon);
	background: transparent;
	color: var(--maroon);
	transition: background .16s ease, color .16s ease;
}
.sh-chip:hover { background: var(--lorange); }
.sh-chip.is-active { background: var(--maroon); color: #FFF6F1; }
/* A chip is a <button> when it filters in place and an <a> when it leads to an
   activity category page. Both have to sit on the same line and look the same. */
a.sh-chip, span.sh-chip { display: inline-flex; align-items: center; gap: 8px; line-height: 1.2; }
a.sh-chip:hover { text-decoration: none; }
/* How many are behind the chip. Quieter than the label, and it inherits the
   chip's colour so it flips with it. */
.sh-chip .n { font-weight: 500; opacity: 0.65; margin-left: 6px; font-variant-numeric: tabular-nums; }
a.sh-chip .n, span.sh-chip .n { margin-left: 0; }

/* Activity cards (Things to do). Fix 15: EVERY card in this view carries a
   photograph, so the sub pages stop being a wall of text boxes. */
.sh-activity-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sh-gap-row) var(--sh-gap); }
.sh-activity {
	display: flex; flex-direction: column;
	background: var(--white);
	border-radius: var(--r-card);
	overflow: hidden;
	transition: box-shadow .18s ease, border-radius .32s ease;
}
.sh-activity:hover { box-shadow: 0 10px 26px rgba(22,18,13,.12); border-radius: var(--r-card) var(--r-hover) var(--r-card) var(--r-card); }
.sh-activity-media { aspect-ratio: 3 / 2; background: var(--lorange); overflow: hidden; transition: border-radius .32s ease; }
.sh-activity:hover .sh-activity-media { border-radius: 0 var(--r-hover) 0 0; }
.sh-activity-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.sh-activity:hover .sh-activity-media img { transform: scale(1.04); }
.sh-activity-body { padding: var(--space-lg); display: flex; flex-direction: column; gap: 12px; flex: 1; }
.sh-activity-body h3 { margin: 0; font-size: 1.25rem; }
.sh-activity-body p { font-size: 0.96rem; margin: 0; }
.sh-activity-body .sh-btn { margin-top: var(--space-xs); align-self: flex-start; padding: 11px 24px; font-size: 0.92rem; }
.sh-activity-meta {
	font-size: 0.78rem; font-weight: 600; letter-spacing: 0.1em;
	text-transform: uppercase; color: var(--coral);
}

/* 11 Sep 2026: the cards are real activities from the database, so three things
   the hardcoded set never needed. */

/* The picture is a link to the activity now, so it has to behave like a block. */
a.sh-activity-media { display: block; }
/* The destination, after the category, on a card that could be from anywhere
   (a category page, the search results). Quieter than the category. */
.sh-activity-place { color: var(--ink-soft); letter-spacing: 0.06em; }
/* The title is a link, but it is the card's own type: no underline until hover. */
.sh-activity-body h3 a { color: inherit; text-decoration: none; }
.sh-activity-body h3 a:hover { color: var(--maroon); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
/* An activity with no photograph yet. Not a grey box: the category, set in the
   brand's display serif on the warm tint the media box already uses. */
.sh-activity-media.is-placeholder { display: grid; place-items: center; padding: var(--space-md); text-align: center; }
.sh-activity-ph {
	font-family: var(--sh-display);
	font-size: clamp(1.1rem, 2.4vw, 1.5rem);
	color: var(--maroon);
	opacity: 0.72;
}

/* "Show more" under a paged activity grid (chrome.js adds the button). */
.sh-show-more { display: block; margin: var(--space-lg) auto 0; }

/* The venue's own website, under an activity's description. */
.sh-activity-visit {
	margin-top: var(--space-lg);
	display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
}
.sh-activity-host { font-size: 0.9rem; color: var(--ink-soft); word-break: break-word; }

/* Destination cards (Things to do index). */
.sh-dest-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sh-gap-row) var(--sh-gap); }
.sh-dest {
	position: relative; display: block;
	aspect-ratio: 4 / 3;
	border-radius: var(--r-card);
	overflow: hidden;
	background: var(--lorange-deep);
}
.sh-dest { transition: box-shadow .18s ease; }
.sh-dest img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.sh-dest:hover img,
.sh-dest:focus-visible img { transform: scale(1.05); }
.sh-dest:hover { box-shadow: 0 10px 26px rgba(22,18,13,.16); }
.sh-dest:focus-visible { outline: 3px solid var(--maroon); outline-offset: 3px; }
.sh-dest::after {
	content: ""; position: absolute; inset: 0;
	background: linear-gradient(180deg, rgba(22,18,13,0) 46%, rgba(22,18,13,.60) 100%);
}
.sh-dest-body { position: absolute; left: 22px; right: 22px; bottom: 20px; z-index: 2; color: #FFF9F4; }
/* Both of these are inline spans in the markup, so they need to be told to
   stack: left inline the count ran into the end of the destination name. */
.sh-dest-body .t { display: block; font-family: var(--sh-display); font-size: 1.6rem; line-height: 1.1; }
.sh-dest-body .c { display: block; margin-top: 4px; font-size: 0.85rem; opacity: .9; }

/* ================================================================ CONTACT
   ROUND 3, fix 17. The old page opened with three equal cards and put the form
   under them, so nothing claimed the eye. Now there is one obvious thing to
   look at: the message form, as the large white card on the left, with the
   ways to reach us stacked quietly beside it. */

.sh-contact-layout {
	display: grid;
	grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
	gap: var(--space-2xl);
	align-items: start;
}
.sh-contact-form-card {
	background: var(--white);
	border-radius: var(--r-card);
	padding: var(--space-2xl);
	box-shadow: var(--sh-shadow-card);
}
.sh-contact-form-card h2 { font-size: clamp(1.7rem, 2.6vw, 2.3rem); margin-bottom: var(--space-sm); }
.sh-contact-aside { display: flex; flex-direction: column; gap: var(--space-md); }
.sh-contact-block {
	background: var(--lorange);
	border-radius: var(--r-card);
	padding: var(--space-lg);
}
.sh-contact-block h3 { font-size: 1.2rem; margin-bottom: var(--space-2xs); }
.sh-contact-block p { font-size: 0.97rem; margin-bottom: 6px; }
.sh-contact-block p:last-child { margin-bottom: 0; }
.sh-contact-block a { font-weight: 600; }
.sh-contact-block .ico {
	width: 44px; height: 44px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: 50%;
	background: var(--maroon); color: var(--lorange);
	margin-bottom: var(--space-sm);
	font-size: 1.05rem;
}
/* The owner block is the one place the page sends a different audience
   somewhere else, so it is set apart rather than dressed as a third option. */
/* Round 5, fix 3: white and the card shadow rather than stone plus a stroke. */
.sh-contact-block-owner { background: var(--white); box-shadow: var(--sh-shadow-card); }

/* ============================ FEATURE ROWS (The Stayhub Difference, fix 16)
   Alternating image and copy, following the design line of the interim site's
   Difference page (its section order and rhythm) but on OUR spacing scale and
   in our type, which is where that page currently falls down. The image in
   each row carries the sculpted corner, alternating side to side so the page
   has a swing to it rather than a stack of identical blocks. */
.sh-feature-rows { display: flex; flex-direction: column; gap: var(--space-3xl); }
.sh-feature-row {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: var(--space-2xl);
	align-items: center;
}
.sh-feature-row .media {
	/* Same device as the About Us timeline: three corners swept, the fourth
	   left square and pointing in at the copy beside it, so the row reads as
	   one thing rather than a picture next to some words. Odd rows put the
	   picture on the left, so its point is bottom right. */
	border-radius: var(--r-hero) var(--r-hero) 0 var(--r-hero);
	overflow: hidden;
	aspect-ratio: 4 / 3;
	background: var(--lorange-deep);
}
.sh-feature-row:nth-child(even) .media {
	border-radius: var(--r-hero) var(--r-hero) var(--r-hero) 0;
	order: 2;
}
.sh-feature-row .media img { width: 100%; height: 100%; object-fit: cover; }
.sh-feature-row .copy h3 { font-size: clamp(1.6rem, 2.5vw, 2.15rem); margin-bottom: var(--space-sm); }
.sh-feature-row .copy .num {
	display: inline-flex; align-items: center; justify-content: center;
	width: 42px; height: 42px; border-radius: 50%;
	background: var(--acid); color: var(--cta-ink);
	font-family: var(--sh-body); font-weight: 600;
	margin-bottom: var(--space-sm);
}

/* Book-direct benefits, three up (the interim page's SAVE MORE / PRIORITY
   SERVICE / MORE FLEXIBILITY beat, in our approved wording). */
.sh-benefit-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sh-gap); }
.sh-benefit {
	background: var(--white);
	border-radius: var(--r-card);
	padding: var(--space-xl) var(--space-lg);
	text-align: left;
}
.sh-benefit .ico {
	width: 56px; height: 56px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: 50%;
	background: var(--lorange); color: var(--maroon);
	font-size: 1.3rem;
	margin-bottom: var(--space-md);
}
.sh-benefit h3 {
	font-family: var(--sh-body);
	font-size: 0.82rem; font-weight: 600;
	letter-spacing: 0.16em; text-transform: uppercase;
	color: var(--coral);
	margin-bottom: var(--space-2xs);
}
.sh-benefit p { font-size: 1.02rem; color: var(--ink); margin: 0; }

/* A page-lead image band, used at the top of the Difference page so it opens
   with a picture rather than a paragraph. */
.sh-page-hero {
	position: relative;
	min-height: 460px;
	display: flex; align-items: flex-end;
	background: var(--maroon-deep) center/cover no-repeat;
	border-radius: 0 0 var(--r-hero) 0;
	overflow: hidden;
	padding: var(--space-3xl) 0;
}
/* TWO scrims, not one.
   30 Sep 2026: the single vertical wash was tuned for a hero whose copy sat on
   the floor of the frame, so it went almost clear (.06) across the middle third.
   The About Us hero has a heading AND a lede AND a button stacked up into that
   band, over a bright white villa, and the heading was close to unreadable.
   A LEFT-WEIGHTED horizontal wash now carries the copy column, and the vertical
   one is kept for the foot of the frame where the cream page meets the
   photograph. Both are needed: the horizontal alone leaves the bottom edge
   fizzing, the vertical alone is what failed. */
.sh-page-hero::after {
	content: "";
	position: absolute; inset: 0;
	background:
		linear-gradient(94deg, rgba(22,18,13,.76) 0%, rgba(22,18,13,.58) 34%, rgba(22,18,13,.24) 62%, rgba(22,18,13,0) 88%),
		linear-gradient(180deg, rgba(22,18,13,.34) 0%, rgba(22,18,13,.10) 30%, rgba(22,18,13,.34) 72%, rgba(22,18,13,.62) 100%);
}
.sh-page-hero > * { position: relative; z-index: 2; width: 100%; }
.sh-page-hero h1 { color: #FFF9F4; max-width: 18ch; text-shadow: 0 2px 24px rgba(22,18,13,.34); }
.sh-page-hero .sh-lede { color: #F6E9E1; max-width: 54ch; text-shadow: 0 1px 16px rgba(22,18,13,.5); }
.sh-page-hero .sh-eyebrow { color: var(--acid); }
/* 30 Sep 2026: the optional hero CTA, which is how the owners' About page
   opens. Acid pill on the photograph, under the lede. */
.sh-page-hero-cta { margin: var(--space-lg) 0 0; }

/* ------------------------------------- destination chips
   Round 3 put a "Where are you headed?" picker in the Things to do opener;
   round 5 (fix 4) removed it, since the destination grid does that job. The
   chips survive as the destination links on the search results page. */
.sh-dest-chips { display: flex; flex-wrap: wrap; gap: 12px; }
.sh-dest-chips a {
	font-family: var(--sh-body); font-weight: 600; font-size: 0.95rem;
	background: var(--lorange);
	color: var(--maroon);
	border-radius: var(--r-pill);
	padding: 12px 22px;
	transition: background .16s ease, color .16s ease;
}
.sh-dest-chips a:hover { background: var(--maroon); color: #FFF6F1; text-decoration: none; }

/* Fix 14: the Insights and blog slot. The pattern is built and labelled now so
   that the day the blog starts publishing, the section fills itself. */
.sh-soon {
	background: var(--white);
	box-shadow: var(--sh-shadow-card);
	border-radius: var(--r-card);
	padding: var(--space-xl);
	text-align: center;
	color: var(--ink-soft);
}
.sh-soon strong { display: block; color: var(--maroon); font-weight: 600; margin-bottom: 6px; }

/* =========================================================== LISTING PAGE */

/* ROUND 4, fix 4: the listing page's anchor bar takes the same mid orange as
   the results band, and the same maroon-on-coral rule for the reason set out
   there. Hover is the deeper maroon plus an underline rather than acid: acid on
   coral does not separate the two, and a link bar wants an unmistakable hover. */
.sh-anchor-nav {
	position: sticky; top: 84px; z-index: 40;
	background: var(--coral);
	color: var(--maroon);
}
.sh-anchor-nav .inner {
	max-width: var(--wrap); margin: 0 auto;
	padding: 0 var(--wrap-pad);
	display: flex; align-items: center; gap: 26px;
	overflow-x: auto;
	white-space: nowrap;
	min-height: 56px;
	scrollbar-width: none;
}
.sh-anchor-nav .inner::-webkit-scrollbar { display: none; }
.sh-anchor-nav a { color: var(--maroon); font-weight: 600; font-size: 0.92rem; padding: 17px 0; }
.sh-anchor-nav a:hover { color: var(--maroon-deep); text-decoration: underline; text-underline-offset: 5px; }
.sh-anchor-actions { margin-left: auto; display: flex; gap: 8px; }
.sh-anchor-actions .chip {
	display: inline-flex; align-items: center; gap: 4px;
	color: var(--maroon);
	background: rgba(255,249,244,.55);
	border: 1px solid rgba(92,14,7,.34);
	border-radius: var(--r-ctl);
	padding: 5px 10px;
	font-size: 0.8rem;
	font-weight: 600;
}

/* Gallery: a static grid. No property photo carousel anywhere (comment #187). */
.sh-gallery {
	display: grid;
	grid-template-columns: 2fr 1fr;
	gap: 14px;
	margin-bottom: 14px;
}
/* THE ONE SCULPTED CORNER on a listing page. The main gallery frame is that
   page's lead image, so it carries the device and every other frame on the page
   takes the quiet card radius. */
/* The tiles are buttons now (round 4, fix 5), so the browser's own button box
   is taken off them and they keep behaving as picture frames. */
.sh-gallery-main,
.sh-gallery-thumb {
	display: block;
	width: 100%;
	padding: 0;
	border: none;
	font: inherit;
	cursor: pointer;
	position: relative;
	overflow: hidden;
	background: var(--stone);
}
.sh-gallery-main {
	border-radius: var(--r-card) var(--r-hero) var(--r-card) var(--r-card);
	aspect-ratio: 3 / 2;
}
.sh-gallery-main img { width: 100%; height: 100%; object-fit: cover; }
.sh-gallery-side { display: grid; grid-template-rows: 1fr 1fr; gap: 14px; }
.sh-gallery-thumb {
	height: 100%;
	border-radius: var(--r-card);
}
.sh-gallery-thumb img { width: 100%; height: 100%; object-fit: cover; }
.sh-gallery-main img,
.sh-gallery-thumb img { transition: transform .4s ease; }
.sh-gallery-main:hover img,
.sh-gallery-thumb:hover img { transform: scale(1.03); }
.sh-gallery-thumb.more::after {
	content: attr(data-more);
	position: absolute; inset: 0;
	display: flex; align-items: center; justify-content: center;
	background: rgba(92,14,7,.72);
	color: #FFF6F1;
	font-weight: 600;
	font-size: 0.98rem;
}
.sh-gallery-thumb.more:hover::after { background: rgba(92,14,7,.82); }
.sh-photo-counter {
	position: absolute; left: 14px; bottom: 14px;
	background: rgba(247,245,240,.94);
	color: var(--maroon);
	font-size: 0.85rem; font-weight: 600;
	padding: 6px 12px;
	border-radius: var(--r-ctl);
}
.sh-share-row { display: flex; justify-content: flex-end; margin-bottom: var(--space-md); }
.sh-share-btn {
	background: transparent;
	border: 1.5px solid var(--maroon);
	color: var(--maroon);
	border-radius: var(--r-btn);
	padding: 9px 20px;
	font-size: 0.92rem;
	font-weight: 600;
}
.sh-share-btn:hover { background: var(--maroon); color: #FFF6F1; }

/* minmax(0, 1fr) rather than 1fr, and min-width:0 on the child, everywhere
   this column appears.
   A grid item defaults to min-width:auto, so the column grows to the widest
   thing inside it. The 12-month availability strip is a 3886px flex track, and
   with a plain `1fr` that measurement escaped its scroll container and stretched
   the whole page to 3886px on a 375px phone. Capping the minimum at 0 keeps the
   strip scrolling inside its own viewport, which is what it is there for. */
.sh-detail-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 396px;
	gap: var(--space-2xl);
	align-items: start;
}
.sh-detail-main { min-width: 0; }
.sh-cal-viewport { max-width: 100%; }
.sh-detail-main h1 { font-size: clamp(2rem, 3.2vw, 2.8rem); margin-bottom: var(--space-xs); }
.sh-rating-pill {
	display: inline-flex; align-items: center; gap: 6px;
	background: var(--lorange);
	color: var(--maroon);
	font-weight: 600;
	padding: 6px 14px;
	border-radius: var(--r-ctl);
	font-size: 0.92rem;
}
.sh-spec-row { display: flex; gap: var(--space-lg); margin: var(--space-md) 0 var(--space-sm); flex-wrap: wrap; }
.sh-spec .n { font-family: var(--sh-display); font-size: 1.9rem; color: var(--maroon); display: block; line-height: 1; }
.sh-spec .l { font-size: 0.8rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-soft); }
.sh-loc-type { display: flex; gap: 26px; flex-wrap: wrap; font-size: 0.96rem; color: var(--ink-soft); }
.sh-loc-type b { color: var(--maroon); font-weight: 600; }

.sh-detail-section { padding: var(--space-xl) 0; border-bottom: 1px solid var(--line); }
.sh-detail-section h2 { font-size: clamp(1.6rem, 2.4vw, 2.1rem); margin-bottom: var(--space-md); }
.sh-desc-block.is-collapsed { max-height: 300px; overflow: hidden; position: relative; }
.sh-desc-block.is-collapsed::after {
	content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 90px;
	background: linear-gradient(180deg, rgba(247,245,240,0), var(--cream));
}
.sh-desc-block h4 { color: var(--maroon); margin: 1.3em 0 .5em; font-family: var(--sh-body); font-weight: 600; letter-spacing: .02em; }
.sh-desc-list { list-style: none; padding: 0; margin: 0 0 1.1em; display: grid; gap: 8px; }
.sh-desc-list li { padding-left: 26px; position: relative; }
.sh-desc-list li::before { content: "\2713"; position: absolute; left: 0; color: var(--coral); font-weight: 600; }
.sh-readmore {
	margin-top: 14px;
	background: transparent;
	border: none;
	color: var(--maroon);
	font-weight: 600;
	border-bottom: 2px solid var(--coral);
	padding: 0 0 3px;
}

.sh-legend { display: flex; gap: 20px; flex-wrap: wrap; font-size: 0.88rem; margin-bottom: 18px; }
.sh-legend i { display: inline-block; width: 15px; height: 15px; border-radius: var(--r-ctl); margin-right: 7px; vertical-align: -2px; }
.lg-avail   { background: var(--white); border: 1.5px solid var(--line); }
.lg-unavail { background: #E6DED4; }
.lg-in      { background: var(--acid); }
.lg-out     { background: var(--coral); }

.sh-cal-controls { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 14px; }
.sh-cal-nav button {
	width: 40px; height: 40px;
	border-radius: 50%;
	border: 1.5px solid var(--maroon);
	background: transparent; color: var(--maroon);
}
.sh-cal-nav button[disabled] { opacity: .3; cursor: not-allowed; }
.sh-cal-viewport { overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: thin; }
.sh-cal-track { display: flex; gap: 26px; }
.sh-cal-track .month { flex: 0 0 300px; scroll-snap-align: start; }
.month h4 { font-family: var(--sh-display); color: var(--maroon); font-size: 1.15rem; margin-bottom: 10px; }
.dow, .days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.dow span { font-size: 0.7rem; text-align: center; color: var(--ink-soft); letter-spacing: .06em; }
.days { margin-top: 6px; }
.day {
	aspect-ratio: 1 / 1;
	display: flex; align-items: center; justify-content: center;
	font-size: 0.85rem;
	border-radius: var(--r-ctl);
	background: var(--white);
	border: 1px solid var(--line);
	color: var(--offblack);
}
.day.empty { background: transparent; border: none; }
.day.past { background: transparent; border-color: transparent; color: #C8C1B7; }
.day.unavail { background: #E6DED4; border-color: #E6DED4; color: #9C9285; text-decoration: line-through; }
.day.pick { cursor: pointer; }
.day.pick:hover { background: var(--lorange); border-color: var(--coral); }
.day.sel-in  { background: var(--acid); border-color: var(--acid); color: var(--cta-ink); font-weight: 600; }
.day.sel-out { background: var(--coral); border-color: var(--coral); color: var(--maroon-deep); font-weight: 600; }
.day.in-range { background: var(--lorange); border-color: var(--lorange); }

.sh-bedding-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: var(--space-sm); }
.sh-bed-room {
	background: var(--white);
	border-radius: var(--r-card);
	padding: 20px;
}
.sh-bed-room .rn { font-weight: 600; color: var(--maroon); margin-bottom: 8px; }
.sh-bed-room .bed { font-size: 0.94rem; }

.sh-amen-count {
	font-family: var(--sh-body);
	font-size: 0.85rem;
	background: var(--lorange);
	color: var(--maroon);
	padding: 3px 10px;
	border-radius: var(--r-ctl);
	vertical-align: middle;
}
.sh-amen-groups { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: var(--space-md); }
.sh-amen-groups h4 { color: var(--maroon); font-family: var(--sh-body); font-weight: 600; font-size: 0.98rem; }
.sh-amen-groups ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 6px; }
.sh-amen-groups li { font-size: 0.94rem; padding-left: 20px; position: relative; }
.sh-amen-groups li::before { content: "\2022"; position: absolute; left: 4px; color: var(--coral); }
.sh-amen-cat.is-hidden { display: none; }
.sh-amen-groups.show-all .sh-amen-cat.is-hidden { display: block; }

.sh-qa-teaser {
	background: var(--lorange);
	border-radius: var(--r-card);
	padding: var(--space-lg);
}

/* ------------------------------------------------------- booking sidebar */

/* ROUND 4, fix 6. Two things were wrong and both are fixed here.

   The COLUMN sticks, not the panel. `.sh-detail-layout` is `align-items:
   start`, which shrink-wraps the aside to the height of the panel inside it, so
   a sticky panel had no distance to travel and let go as soon as its own box
   scrolled past. A sticky grid item is measured against its grid AREA instead,
   and the area is the full height of the row, so the column now travels beside
   the whole left hand column, all the way to the FAQs.

   And the panel is allowed to be taller than the window. With a twelve month
   calendar and a full quote in it the panel can pass 800px, which on a laptop
   is more than the space under the two sticky bars. Left alone the bottom of
   the panel, BOOK NOW included, would be unreachable. It gets its own scroll
   when that happens, so the overflow is inside the panel rather than off the
   screen. The scroll is on the panel itself rather than on the column, so the
   panel's rounded corners clip it and the panel's shadow is not cut off. */
.sh-detail-side {
	position: sticky;
	top: 156px;                     /* header 84 + anchor bar 56 + 16 of air */
	align-self: start;
	min-width: 0;
}
.sh-booking-panel {
	position: static;
	max-height: calc(100vh - 176px);
	overflow-y: auto;
	background: var(--white);
	border-radius: var(--r-card);
	padding: var(--space-md);
	box-shadow: 0 1px 2px rgba(22,18,13,.05), 0 20px 44px rgba(22,18,13,.09);
	scrollbar-width: thin;
}
.sh-from-price { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }
.sh-from-price .amount { font-family: var(--sh-display); font-size: 2.1rem; color: var(--maroon); }
.sh-bp-title { font-weight: 600; color: var(--offblack); margin: 16px 0 10px; }
.sh-bp-cal .sh-cal-controls { margin-bottom: 8px; }
.sh-bp-cal .mlabel { font-family: var(--sh-display); color: var(--maroon); font-size: 1.05rem; }
.sh-bp-dates { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 16px 0; }
.sh-bp-date {
	border: 1.5px solid var(--line);
	border-radius: var(--r-ctl);
	padding: 10px 14px;
}
.sh-bp-date .lab { font-size: 0.68rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-soft); }
.sh-bp-date .val { font-weight: 600; color: var(--offblack); font-size: 0.95rem; }

.sh-avail-note { border-radius: var(--r-ctl); padding: 11px 15px; font-size: 0.92rem; margin: 12px 0; }
.sh-avail-ok  { background: #EEF2D6; color: #4A5210; }
.sh-avail-bad { background: #FBE3DA; color: #8A2A12; }

.sh-quote-box { border-top: 1px solid var(--line); margin-top: 14px; padding-top: 14px; }
.sh-quote-line { display: flex; justify-content: space-between; gap: 12px; font-size: 0.94rem; padding: 5px 0; }
.sh-quote-line.excluded { color: var(--ink-soft); font-size: 0.86rem; }
.sh-quote-total {
	display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
	border-top: 1.5px solid var(--maroon);
	margin-top: 10px; padding-top: 12px;
	font-weight: 600; color: var(--maroon);
}
.sh-quote-total .big { font-family: var(--sh-display); font-size: 1.55rem; }
.sh-hint { font-size: 0.82rem; color: var(--ink-soft); text-align: center; margin: 10px 0 0; }
.sh-bp-links { display: flex; flex-direction: column; gap: 9px; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.sh-bp-links a { font-size: 0.9rem; color: var(--ink-soft); }
.sh-bp-links a:hover { color: var(--maroon); }

/* Mobile sticky book bar: only appears on small screens. */
.sh-mobile-book {
	display: none;
	position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
	background: var(--cream);
	border-top: 1px solid var(--line);
	padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
	box-shadow: 0 -12px 28px rgba(22,18,13,.12);
	align-items: center;
	gap: 14px;
}
.sh-mobile-book .p { flex: 1; min-width: 0; }
.sh-mobile-book .p .amount { font-family: var(--sh-display); font-size: 1.35rem; color: var(--maroon); display: block; line-height: 1.1; }
.sh-mobile-book .p .sub { font-size: 0.78rem; color: var(--ink-soft); }
.sh-mobile-book .sh-btn { flex-shrink: 0; }

/* ================================================================ CHECKOUT */

.sh-checkout-layout { display: grid; grid-template-columns: 1.35fr 1fr; gap: var(--space-xl); align-items: start; }
.sh-form-card, .sh-summary-card {
	background: var(--white);
	border-radius: var(--r-card);
	box-shadow: var(--sh-shadow-card);
	padding: var(--space-lg);
}
.sh-summary-card { position: sticky; top: 110px; }

/* ----------------------------------------- the card field and its warnings
   LIVE BOOKINGS, 1 Oct 2026.

   .sh-card-field is the box Stripe mounts its own iframes into. Almost nothing
   is styled here on purpose: the inputs inside belong to Stripe's document,
   not ours, and are themed through the Elements `appearance` object in app.js
   instead. What this rule owns is the box around them, so the payment block
   sits on the same rhythm as the name and email fields above it.

   .sh-demo-notice-live is the one that matters. The ordinary notice is quiet
   and informational, because "nothing will be charged" is reassuring. This one
   is coral on light orange with a real border, because "this will charge a
   real card" is the opposite of reassuring and the banner should feel like it.
   Maroon on light orange, not white on coral: 4.9:1 against 2.8:1. */
.sh-card-field {
	background: var(--white);
	border: 1px solid var(--line);
	border-radius: var(--r-ctl);
	padding: var(--space-sm);
	min-height: 90px;
}
.sh-demo-notice-live {
	background: var(--lorange);
	border: 2px solid var(--coral);
	color: var(--maroon);
}
.sh-form-error {
	background: #FDECEA;
	border-left: 4px solid #B3261E;
	color: #7A1B12;
	border-radius: var(--r-ctl);
	padding: 12px 16px;
	margin: var(--space-sm) 0 0;
	font-size: 0.95rem;
}
.sh-btn[disabled] { opacity: 0.55; cursor: progress; }
.sh-summary-property { display: flex; gap: 14px; margin-bottom: 18px; }
.sh-summary-property img { width: 88px; height: 72px; object-fit: cover; border-radius: var(--r-ctl); }
.sh-summary-property .n { font-weight: 600; color: var(--offblack); line-height: 1.3; }
.sh-summary-meta { font-size: 0.88rem; color: var(--ink-soft); }
.sh-confirm-state { text-align: center; padding: 24px 0; }
.sh-confirm-tick {
	width: 66px; height: 66px; margin: 0 auto 18px;
	display: flex; align-items: center; justify-content: center;
	border-radius: 50%; background: var(--acid); color: var(--cta-ink);
	font-size: 1.8rem;
}
.sh-confirm-code {
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	background: var(--lorange); color: var(--maroon);
	padding: 4px 12px; border-radius: var(--r-ctl); font-weight: 600;
}

/* ============================================ GALLERY LIGHTBOX (fix 5) */

/* A full-screen viewer for the property's photographs. It opens from any tile
   in the gallery grid, including the "+N more photos" tile, and closes on the
   X, on escape, or on the backdrop. Deliberately not a carousel: it advances
   only when the guest asks it to, and it does not exist until they open it. */
.sh-lightbox {
	position: fixed; inset: 0; z-index: 200;
	display: none;
	/* Solid, not a translucent scrim. At full-screen size the photograph is the
	   whole point and a page showing faintly through the margins is just noise
	   behind it. */
	background: #100C09;
	color: #F6EFE9;
	flex-direction: column;
}
.sh-lightbox.is-open { display: flex; }
body.sh-lightbox-open { overflow: hidden; }

.sh-lb-top {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--space-md);
	padding: 14px clamp(14px, 3vw, 28px);
	flex: 0 0 auto;
}
.sh-lb-count { font-family: var(--sh-body); font-size: 0.92rem; font-weight: 600; letter-spacing: .04em; }
/* The controls sit over the photograph, so they carry their own dark disc
   rather than a wash of white at 14%, which vanished completely against a
   bright sky or a lawn. Dark fill, light edge, light glyph: legible on any
   picture the properties throw at it. */
.sh-lb-close,
.sh-lb-nav {
	background: rgba(16,12,9,.66);
	color: #F6EFE9;
	border: 1.5px solid rgba(246,239,233,.6);
	border-radius: 50%;
	box-shadow: 0 4px 18px rgba(0,0,0,.4);
	transition: background .16s ease, color .16s ease;
}
.sh-lb-close:hover,
.sh-lb-nav:hover { background: #F6EFE9; color: var(--offblack); border-color: #F6EFE9; }
.sh-lb-close {
	display: inline-flex; align-items: center; justify-content: center;
	width: 46px; height: 46px;
	font-size: 1.1rem;
	line-height: 1;
}

.sh-lb-stage {
	position: relative;
	flex: 1 1 auto;
	min-height: 0;
	display: flex; align-items: center; justify-content: center;
	padding: 0 clamp(14px, 3vw, 28px);
}
.sh-lb-stage img {
	max-width: 100%;
	max-height: 100%;
	width: auto; height: auto;
	object-fit: contain;
	border-radius: var(--r-card);
	background: #241C16;
}
.sh-lb-nav {
	position: absolute; top: 50%; transform: translateY(-50%);
	display: inline-flex; align-items: center; justify-content: center;
	width: 54px; height: 54px;
	font-size: 1.5rem;
	line-height: 1;
}
.sh-lb-prev { left: clamp(8px, 2vw, 26px); }
.sh-lb-next { right: clamp(8px, 2vw, 26px); }

.sh-lb-cap {
	flex: 0 0 auto;
	padding: 14px clamp(14px, 3vw, 28px) calc(18px + env(safe-area-inset-bottom));
	font-size: 0.92rem;
	color: #CFC2B9;
	text-align: center;
	min-height: 20px;
}

@media (max-width: 760px) {
	.sh-lb-nav { width: 46px; height: 46px; font-size: 1.3rem; }
	.sh-lb-stage { padding: 0 8px; }
	.sh-lb-stage img { border-radius: var(--r-ctl); }
}

/* ========================================================= TRACKING PANEL */

#sh-track-panel { position: fixed; right: 18px; bottom: 18px; z-index: 90; font-family: var(--sh-body); }
#sh-track-panel .tp-pill {
	display: inline-flex; align-items: center; gap: 9px;
	background: var(--maroon); color: #FFF6F1;
	border: none; border-radius: var(--r-ctl);
	padding: 11px 20px; font-size: 0.88rem; font-weight: 600;
	box-shadow: 0 10px 26px rgba(22,18,13,.2);
}
#sh-track-panel .tp-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--acid); }
#sh-track-panel .tp-dot.flash { animation: sh-flash .6s ease; }
@keyframes sh-flash { 0%,100% { opacity: 1; } 50% { opacity: .2; transform: scale(1.6); } }
#sh-track-panel .tp-count { background: rgba(255,255,255,.2); border-radius: var(--r-ctl); padding: 1px 9px; font-size: 0.78rem; }
#sh-track-panel .tp-panel {
	display: none;
	width: min(400px, calc(100vw - 36px));
	max-height: min(520px, 70vh);
	background: #201812; color: #EFE6DF;
	border-radius: var(--r-card);
	overflow: hidden;
	flex-direction: column;
	box-shadow: 0 22px 50px rgba(22,18,13,.4);
}
#sh-track-panel.open .tp-panel { display: flex; }
#sh-track-panel.open .tp-pill { display: none; }
#sh-track-panel .tp-header { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 14px 16px; border-bottom: 1px solid rgba(255,255,255,.12); font-size: 0.85rem; }
#sh-track-panel .tp-header .g { color: var(--acid); }
#sh-track-panel .tp-btn { background: transparent; border: 1px solid rgba(255,255,255,.28); color: #EFE6DF; border-radius: var(--r-ctl); padding: 4px 12px; font-size: 0.78rem; margin-left: 6px; }
#sh-track-panel .tp-events { overflow-y: auto; padding: 10px 14px; flex: 1; }
#sh-track-panel .tp-empty { font-size: 0.82rem; color: #A99C93; padding: 18px 2px; }
#sh-track-panel .tp-event { border-bottom: 1px solid rgba(255,255,255,.09); padding: 10px 0; }
#sh-track-panel .ev-top { display: flex; justify-content: space-between; gap: 10px; }
#sh-track-panel .ev-name { color: var(--acid); font-weight: 600; font-size: 0.85rem; }
#sh-track-panel .ev-time { font-size: 0.75rem; color: #A99C93; }
#sh-track-panel .ev-body { white-space: pre-wrap; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.74rem; color: #CFC2B9; margin-top: 5px; }
#sh-track-panel .tp-foot { padding: 10px 16px; font-size: 0.74rem; color: #A99C93; border-top: 1px solid rgba(255,255,255,.12); }

/* ============================================== ELEMENTOR BUTTON WIDGET */

/* The global kit deliberately does not style buttons (see elementor-builder.php:
   its `.elementor-kit-N button` rule outranks every brand component class).
   So the brand stylesheet owns the builder's Button widget too, and the team
   gets the acid pill by default when they drop one on a page. A widget given a
   secondary variant takes the square secondary shape, exactly as .sh-btn does. */
.elementor-button,
.elementor-button-link {
	display: inline-flex; align-items: center; justify-content: center; gap: 10px;
	font-family: var(--sh-body);
	font-weight: 600;
	font-size: 1rem;
	padding: 15px 32px;
	border: 2px solid var(--acid);
	border-radius: var(--r-pill);
	background: var(--acid);
	color: var(--cta-ink);
	text-align: center;
	transition: background .16s ease, border-color .16s ease, box-shadow .16s ease;
}
.elementor-button:focus-visible,
.elementor-button-link:focus-visible { outline: 3px solid var(--maroon); outline-offset: 3px; }
.elementor-button:hover,
.elementor-button-link:hover {
	background: var(--acid-deep);
	border-color: var(--acid-deep);
	color: var(--cta-ink);
	text-decoration: none;
}
/* A button widget the team has given the sh-btn-* classes keeps that variant. */
.elementor-button.sh-btn-maroon { background: var(--maroon); border-color: var(--maroon); color: #FFF6F1; border-radius: var(--r-btn); }
.elementor-button.sh-btn-coral  { background: var(--coral); border-color: var(--coral); color: var(--maroon-deep); }
.elementor-button.sh-btn-ghost  { background: transparent; border-color: var(--maroon); color: var(--maroon); border-radius: var(--r-btn); }

/* ------------------------------------------------ ELEMENTOR KIT GUARD */

/* The global kit carries the round-2 button radius (4px), and it compiles that
   into `.elementor-kit-N button, ... .elementor-kit-N .elementor-button`, which
   is specificity (0,1,1) and outranks a bare component class. Four shapes on
   this site are deliberately NOT 4px, so they are restated here at matching
   specificity. The brand stylesheet is enqueued with the kit as a dependency
   (stayhub_style_deps in the theme's functions.php), so it prints afterwards
   and a tie resolves in favour of the design. */
body .sh-btn-acid,
body .sh-btn-coral,
body .elementor-button,
body .elementor-button-link { border-radius: var(--r-pill); }
body .sh-save,
body .sh-cal-nav button,
body .sh-carousel-nav button { border-radius: 50%; }
/* Round 5: the guard was missing every <button> added in rounds 3 and 4, so
   the kit's 4px was quietly squaring them off: the pill Filters, Map and Clear
   filters controls on /rentals/, the round card-gallery arrows, the lightbox
   controls, and (the one that mattered most) the listing gallery's main frame,
   whose sculpted corner is the page's lead flourish. Restated here at the
   kit's own specificity. */
body .sh-band-btn,
body .sh-drawer-clear { border-radius: var(--r-pill); }
body .sh-gal-btn,
body .sh-lb-close,
body .sh-lb-nav { border-radius: 50%; }
body .sh-gallery-main { border-radius: var(--r-card) var(--r-hero) var(--r-card) var(--r-card); }
body .sh-gallery-thumb { border-radius: var(--r-card); }
/* An Elementor button the team has recoloured to a secondary variant is
   (0,2,0) and keeps the square shape without needing anything here. */

/* ROUND 6: the same collision, on IMAGES this time, and it cost a whole
   section before it was spotted.

   Elementor's frontend.min.css carries `.elementor img { height: auto }`. That
   is (0,1,1) and beats any bare component class, so a full-bleed cover image
   sized by `height: 100%` silently falls back to its intrinsic aspect ratio.
   On a wide screen nobody notices, because a 3:2 photograph across 1440px is
   taller than the band anyway. On a phone the image collapsed to 250px inside a
   609px band and the Stayhub Difference section rendered as a photograph with
   two thirds of a maroon rectangle under it.

   Restated at (0,2,1) rather than (0,1,1), so this does not depend on load
   order the way the button rules above do. Any future full-bleed cover image
   belongs in this list. */
.sh-hero img.sh-hero-media-img,
.sh-hero .sh-hero-media > img,
.sh-hero video.sh-hero-video,
.sh-difference img.sh-difference-media {
	height: 100%;
	width: 100%;
	object-fit: cover;
}
.sh-perk-media img.sh-perk-img,
.sh-perk .sh-perk-media img { height: 100%; width: 100%; object-fit: cover; }

/* =============================================== ELEMENTOR-ABSENT NOTICE */

.sh-builder-note {
	background: var(--lorange);
	border-left: 4px solid var(--coral);
	color: var(--maroon-deep);
	font-size: 0.9rem;
	padding: 10px 18px;
	text-align: center;
}

/* ======================================= LISTING OPENERS (round 5, 4 and 6)
   The Things to do hub, the guides index and the search results share one
   opener: a light orange band with the heading and intro on the left and the
   guide search on the right, bottom aligned so the search box sits on the
   same line as the last line of copy. Things to do is the Figma frame's shape
   again (a hero, then the destination grid), without round 3's second
   "Where are you headed?" box. */
.sh-listing-hero-grid {
	display: grid;
	grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
	gap: var(--space-lg) var(--space-3xl);
	align-items: end;
}
.sh-listing-hero-copy h1 { margin-bottom: 0; }
.sh-listing-hero-copy .sh-lede { margin: var(--space-sm) 0 0; }
.sh-ttd-sub {
	font-size: 1.32rem;
	color: var(--maroon);
	margin: var(--space-xs) 0 0;
}
.sh-ttd-hero .sh-lede { max-width: 60ch; }

/* ------------------------------------------------ the guide search box */
.sh-search-form { width: 100%; }
.sh-search-form-label {
	display: block;
	font-family: var(--sh-body);
	font-size: 0.95rem;
	font-weight: 600;
	color: var(--maroon);
	margin-bottom: 10px;
}
.sh-search-form-row {
	display: flex; align-items: center; gap: 8px;
	background: var(--white);
	border-radius: var(--r-pill);
	padding: 6px 6px 6px 20px;
	box-shadow: var(--sh-shadow-card);
	transition: box-shadow .16s ease;
}
.sh-search-form-row:focus-within { box-shadow: 0 0 0 3px rgba(92, 14, 7, .22), var(--sh-shadow-card); }
.sh-search-form-ico { display: inline-flex; color: var(--maroon); flex-shrink: 0; }
.sh-search-form-ico svg { width: 20px; height: 20px; }
.sh-search-form input[type="search"] {
	flex: 1 1 auto; min-width: 0;
	background: transparent;
	border: none;
	border-radius: 0;
	box-shadow: none;
	padding: 12px 6px;
	min-height: 48px;
	color: var(--offblack);
}
.sh-search-form input[type="search"]:focus { box-shadow: none; }
.sh-search-form input[type="search"]::placeholder { color: #8C857C; }
.sh-search-form input[type="search"]::-webkit-search-cancel-button { cursor: pointer; }
.sh-search-form .sh-btn { flex-shrink: 0; padding: 12px 28px; min-height: 48px; }

/* ------------------------------------------ post chips (round 5, fix 5)
   Category and destination, shown the way mainstream blogs show them: small
   filled pills above the title, each one a link to more of the same. Filled,
   never outlined (fix 3). The category is coral, the place light orange. */
.sh-post-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.sh-post-chip {
	display: inline-flex; align-items: center;
	font-family: var(--sh-body);
	font-size: 0.8rem;
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: 0.02em;
	padding: 7px 14px;
	border-radius: var(--r-pill);
	background: var(--lorange);
	color: var(--maroon);
	transition: background .16s ease, color .16s ease;
}
.sh-post-chip-cat { background: var(--coral); color: var(--maroon-deep); }
a.sh-post-chip:hover { background: var(--maroon); color: #FFF6F1; text-decoration: none; }
.sh-post-body .sh-post-chips { margin-bottom: 2px; }
.sh-post-body .sh-post-chip { padding: 5px 11px; font-size: 0.74rem; }

/* The category row on the guides index. */
.sh-cat-chips { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: var(--space-xl); }
.sh-cat-chips .sh-post-chip { font-size: 0.9rem; padding: 10px 20px; background: var(--white); box-shadow: var(--sh-shadow-card); }
.sh-cat-chips .sh-post-chip.is-active { background: var(--maroon); color: #FFF6F1; }

/* ------------------------------------------------ search results page */
.sh-search-subhead { font-size: clamp(1.6rem, 2.4vw, 2.1rem); margin: 0 0 var(--space-md); }
.sh-search-dests { margin-bottom: var(--space-2xl); }
.sh-search-empty { margin-bottom: var(--space-2xl); }
.sh-search-empty h2 { font-size: clamp(1.6rem, 2.6vw, 2.2rem); }
.sh-search-empty p { max-width: 56ch; margin-inline: auto; }

/* Pagination, on the index, the archives and the results. */
.navigation.pagination { margin-top: var(--space-2xl); }
.navigation.pagination .nav-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.navigation.pagination .page-numbers {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: 44px; height: 44px; padding: 0 14px;
	border-radius: var(--r-pill);
	background: var(--white);
	box-shadow: var(--sh-shadow-card);
	color: var(--maroon); font-weight: 600; font-size: 0.95rem;
}
.navigation.pagination .page-numbers.current { background: var(--maroon); color: #FFF6F1; }
.navigation.pagination a.page-numbers:hover { background: var(--lorange); text-decoration: none; }

/* ============================================ ARTICLE (round 5, fix 5)
   Travel guides and blog posts. One reading column, centred, at about 68
   characters; the lead image wider than the column; a real heading ladder.

     measure        68ch of 19px Matter, about 700px
     title          The Seasons, 40 to 68px
     standfirst     the excerpt, 20 to 23px, under the title
     lead           the first paragraph of the body, a step up from the rest
     h2 / h3        serif 30 to 38px / 24px, with 2em above so sections read
                    as sections
     lists          coral dots and maroon numerals, hung so the text aligns
     quotes         serif, maroon, on a coral rule
     lead image     the page's one sculpted corner (the brand device is held
                    to one use per page) */
.sh-article-head { padding: var(--space-2xl) 0 var(--space-xl); }
.sh-article-measure { max-width: 46rem; margin-inline: auto; }
.sh-article-head .sh-breadcrumb { max-width: 46rem; margin-inline: auto; margin-bottom: var(--space-lg); }
.sh-article-head .sh-post-chips { margin-bottom: var(--space-md); }
.sh-article-title {
	font-size: clamp(2.5rem, 5.2vw, 4.25rem);
	line-height: 1;
	margin: 0;
	max-width: 18ch;
}
.sh-article-dek {
	font-size: clamp(1.2rem, 1.6vw, 1.42rem);
	line-height: 1.45;
	color: var(--ink);
	margin: var(--space-md) 0 0;
	max-width: 40ch;
}
.sh-article-meta {
	display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
	margin: var(--space-md) 0 0;
	font-size: 0.9rem;
	color: var(--ink-soft);
}
.sh-article-meta span:first-child { font-weight: 600; color: var(--maroon); }

.sh-article-hero { margin: 0 0 var(--space-2xl); }
.sh-article-hero-frame {
	max-width: 1080px;
	margin-inline: auto;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	border-radius: var(--r-card) var(--r-hero) var(--r-card) var(--r-card);
	background: var(--lorange-deep);
}
.sh-article-hero-frame img { width: 100%; height: 100%; object-fit: cover; }
.sh-article-hero figcaption {
	max-width: 46rem; margin: 10px auto 0;
	font-size: 0.85rem; color: var(--ink-soft);
}

.sh-article-main { padding-bottom: var(--section-y); }
.sh-article-body {
	font-size: 1.1875rem;          /* 19px */
	line-height: 1.72;
	color: var(--ink);
	max-width: min(46rem, 68ch);
}
.sh-article-body > * { margin-top: 0; margin-bottom: 1.15em; }
.sh-article-body > :last-child { margin-bottom: 0; }
/* The lead: the first paragraph, a step larger and darker, so the article has
   a way in before the first heading. */
.sh-article-body > p:first-child {
	font-size: clamp(1.28rem, 1.7vw, 1.44rem);
	line-height: 1.55;
	color: var(--offblack);
	margin-bottom: 1.3em;
}
.sh-article-body h2 {
	font-size: clamp(1.85rem, 2.9vw, 2.4rem);
	line-height: 1.05;
	margin: 1.6em 0 0.5em;
}
.sh-article-body h3 {
	font-size: clamp(1.4rem, 2vw, 1.6rem);
	line-height: 1.12;
	margin: 1.7em 0 0.45em;
}
.sh-article-body h4 {
	font-family: var(--sh-body);
	font-size: 1.05rem; font-weight: 600; letter-spacing: 0.01em;
	color: var(--maroon);
	margin: 1.5em 0 0.4em;
}
.sh-article-body h2 + h3 { margin-top: 0.6em; }
.sh-article-body a {
	color: var(--maroon);
	text-decoration: underline;
	text-decoration-color: var(--coral);
	text-decoration-thickness: 2px;
	text-underline-offset: 3px;
}
.sh-article-body a:hover { text-decoration-color: var(--maroon); }
.sh-article-body strong { color: var(--offblack); font-weight: 600; }

.sh-article-body ul,
.sh-article-body ol { list-style: none; padding: 0; }
.sh-article-body li { position: relative; padding-left: 1.7em; margin-bottom: 0.55em; }
.sh-article-body li > ul, .sh-article-body li > ol { margin-top: 0.55em; margin-bottom: 0; }
.sh-article-body ul > li::before {
	content: "";
	position: absolute; left: 0.35em; top: 0.68em;
	width: 8px; height: 8px; border-radius: 50%;
	background: var(--coral);
}
.sh-article-body ol { counter-reset: sh-ol; }
.sh-article-body ol > li { counter-increment: sh-ol; }
.sh-article-body ol > li::before {
	content: counter(sh-ol) ".";
	position: absolute; left: 0; top: 0;
	font-weight: 600; color: var(--maroon);
}

.sh-article-body blockquote {
	margin: 1.8em 0;
	padding: 0.2em 0 0.2em 1.2em;
	border-left: 4px solid var(--coral);
}
.sh-article-body blockquote p {
	font-family: var(--sh-display);
	font-size: clamp(1.5rem, 2.3vw, 1.9rem);
	line-height: 1.22;
	color: var(--maroon);
	margin: 0 0 0.4em;
}
.sh-article-body blockquote p:last-child { margin-bottom: 0; }
.sh-article-body blockquote cite { display: block; margin-top: 0.6em; font-family: var(--sh-body); font-style: normal; font-size: 0.9rem; color: var(--ink-soft); }

.sh-article-body figure { margin: 2em 0; }
.sh-article-body img { border-radius: var(--r-card); height: auto; }
.sh-article-body figcaption,
.sh-article-body .wp-caption-text { font-size: 0.85rem; color: var(--ink-soft); margin-top: 8px; }
.sh-article-body hr { border: 0; width: 64px; height: 3px; background: var(--coral); margin: 2.4em 0; }
.sh-article-body table { width: 100%; border-collapse: collapse; font-size: 0.95rem; display: block; overflow-x: auto; }
.sh-article-body th, .sh-article-body td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--line); }
.sh-article-body th { color: var(--maroon); font-weight: 600; }

.sh-article-foot {
	display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
	margin-top: var(--space-2xl);
	padding-top: var(--space-md);
	border-top: 1px solid var(--line);
}
.sh-article-foot-label { font-size: 0.85rem; font-weight: 600; color: var(--ink-soft); }

/* ======================================================= ABOUT US: TIMELINE */

/* REBUILT 30 SEP 2026 to the owners' site's own About Us timeline, which is
   what Fiona asked for: their structure, our colours and our words.

   Their structure: a rule down the CENTRE of the page, a dot on each milestone,
   a raised card on one side with the year, headline and copy, and a circular
   photograph opposite it, alternating down the page.

   Ours: the rule is acid, the dots are coral, the cards are Light Orange on the
   stone band, the years are maroon display serif. Teal never appears on this
   site; that is the owner arm's colour world and CLAUDE.md keeps the two apart.

   HOW THE ALTERNATION WORKS. Each row is a three-column grid: card, spine,
   media. Odd rows use the natural order; even rows swap the two outer columns
   with grid-column, so nothing in the markup knows which side it lands on and
   adding a milestone cannot break the rhythm. The spine column is the gap the
   rule runs through. The rule itself is one pseudo-element on the <ol>, not one
   per row, so it never shows a seam between milestones. */
.sh-timeline {
	list-style: none;
	margin: 0;
	padding: 0;
	position: relative;
	display: grid;
	gap: var(--space-2xl);
}
/* The continuous centre rule. Inset top and bottom by half a row so it starts
   and ends at the first and last dot rather than floating past them. */
.sh-timeline::before {
	content: "";
	position: absolute;
	left: 50%;
	top: 60px;
	bottom: 60px;
	width: 4px;
	margin-left: -2px;
	background: var(--acid);
	border-radius: 2px;
}
.sh-timeline-row {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 1fr) 132px minmax(0, 1fr);
	/* Tops flush, not centred. Centring two boxes of different heights lines
	   up neither edge, which is what made the row look untidy: the photograph
	   floated 45px above its card for no reason a reader could see. */
	align-items: start;
}
/* The dot, pinned to the rule rather than to either column, so every marker
   lines up whatever length the copy runs to. */
.sh-timeline-row::before {
	content: "";
	position: absolute;
	left: 50%;
	top: 50%;
	width: 26px; height: 26px;
	margin: -13px 0 0 -13px;
	border-radius: 50%;
	background: var(--coral);
	box-shadow: 0 0 0 6px var(--stone);
	z-index: 1;
}
.sh-timeline-card {
	grid-column: 1;
	/* BOTH are pinned to row 1. Without this, an even row puts the card in
	   column 3 and then grid refuses to place the photograph back in column 1
	   of the same row, so it dropped into a second row underneath. That is
	   what made every other row look out of line. */
	grid-row: 1;
	background: var(--lorange);
	border-radius: var(--r-card);
	padding: var(--space-xl);
	box-shadow: 0 10px 30px rgba(22,18,13,.07);
}
/* The photograph sits against the spine, directly opposite its card, rather
   than floating in the middle of its own column with a gap on both sides. The
   feature rows on the Difference page already pair a picture with its copy
   this way, and it is why those rows read as one thing. */
.sh-timeline-media { grid-column: 3; grid-row: 1; display: flex; justify-content: flex-start; }
/* Even rows swap sides, and the photograph swaps with them so it still leans
   in towards the spine rather than away from it. */
.sh-timeline-row:nth-child(even) .sh-timeline-card  { grid-column: 3; }
.sh-timeline-row:nth-child(even) .sh-timeline-media { grid-column: 1; justify-content: flex-end; }

.sh-timeline-year {
	display: block;
	font-family: var(--sh-display);
	font-size: clamp(1.9rem, 3.2vw, 2.6rem);
	line-height: 1;
	color: var(--maroon);
	margin-bottom: var(--space-xs);
}
.sh-timeline-card h3 { margin: 0 0 0.45em; font-size: 1.28rem; }
.sh-timeline-card p  { margin: 0; color: var(--ink); }

.sh-timeline-media img {
	width: 100%;
	/* Close to the height of the card beside it, so the two finish at roughly
	   the same place as well as starting at it. 380 towered over a 289 card. */
	max-width: 320px;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	/* The brand's rounded-corner device, not a plain circle: three corners
	   swept and one left square. The square corner points INWARDS and DOWNWARDS,
	   at the spine, so each photograph reads as growing off the timeline the
	   way a leaf grows off a branch. Odd rows sit to the right of the spine, so
	   their point is bottom left; even rows sit to the left, so theirs is
	   bottom right. */
	border-radius: 50% 50% 50% 0;
	display: block;
	margin: 0;
}
.sh-timeline-row:nth-child(even) .sh-timeline-media img { border-radius: 50% 50% 0 50%; }

/* =========================================================== ABOUT US: TEAM */

/* Also the owners' site's layout: four across, full-bleed portrait cards with
   the role in small caps and the name under it, set over the foot of the
   photograph. Theirs are teal; ours are Light Orange, because the backdrop was
   recoloured into the guest palette (see stayhub_team() in config.php).

   The caption sits ON the photograph rather than under it, which is what stops
   a row of eight cards turning into a row of eight ragged text blocks of
   different heights. It reads because every one of these is a studio shot on a
   flat sweep, so the bottom of the frame is always the backdrop, never a face.

   Nobody without a headshot gets a grey silhouette: they get a brand monogram
   in the same box, which is a deliberate treatment rather than an apology. */
.sh-team-grid {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--sh-gap);
}
.sh-team-member {
	position: relative;
	border-radius: var(--r-card);
	overflow: hidden;
	background: var(--lorange);
	isolation: isolate;
}
.sh-team-photo {
	width: 100%;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	display: block;
	background: var(--lorange);
}
.sh-team-monogram {
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: var(--sh-display);
	font-size: clamp(2rem, 4vw, 3rem);
	line-height: 1;
	color: var(--maroon);
	letter-spacing: 0.02em;
}
/* A soft foot-of-frame wash, so the caption holds on a pale backdrop without a
   flat bar across the bottom of every portrait. */
.sh-team-caption {
	position: absolute;
	left: 0; right: 0; bottom: 0;
	padding: var(--space-2xl) var(--space-sm) var(--space-sm);
	background: linear-gradient(to top, rgba(250,228,211,.97) 0%, rgba(250,228,211,.88) 42%, rgba(250,228,211,0) 100%);
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.sh-team-role {
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--coral-ink, #B8452A);
}
.sh-team-name {
	font-family: var(--sh-display);
	font-size: 1.24rem;
	line-height: 1.1;
	color: var(--maroon);
}

/* ================================================================= MOBILE */

@media (max-width: 1180px) {
	.sh-detail-layout { grid-template-columns: minmax(0, 1fr) 340px; gap: var(--space-xl); }
	/* Below about a laptop the five segments stop fitting on one line, so the
	   bar becomes two rows of segments and the Search pill goes full width
	   underneath. It is still one continuous bar with rules between the
	   segments, which is the part of the reference that matters. */
	.sh-search { flex-wrap: wrap; max-width: none; }
	.sh-search-bar { grid-template-columns: repeat(3, minmax(0, 1fr)); flex: 1 1 100%; }
	.sh-seg + .sh-seg::before { top: 14%; bottom: 14%; }
	.sh-seg:nth-child(3n + 1)::before { display: none; }
	.sh-seg:nth-child(n + 4) { border-top: 1px solid #E4E3E0; }
	.sh-search-go { flex: 1 1 100%; }
	/* The map keeps its share until the columns get genuinely tight. */
	.sh-results-layout { grid-template-columns: minmax(0, 1fr) 38%; gap: var(--space-lg); }
	.sh-results-col .sh-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 1080px) {
	.sh-tile-grid { grid-template-columns: repeat(3, 1fr); }
	.sh-featured { grid-template-columns: repeat(4, 1fr); }
	.sh-featured > * { grid-column: span 2; }
	.sh-featured > .span-wide { grid-column: 1 / -1; }
	/* Full width at this breakpoint too, but a taller frame: 21:9 across a
	   tablet is a letterbox slot. */
	.sh-featured > .span-wide .sh-card-media { aspect-ratio: 16 / 9; }
	.sh-browse-tile { grid-column: span 2; min-height: 190px; }
	.sh-type-grid { grid-template-columns: repeat(2, 1fr); }
	.sh-post-grid, .sh-activity-grid, .sh-dest-grid { grid-template-columns: repeat(2, 1fr); }
	/* ROUND 6. The 4 + 3 tile layout only earns its keep at full width; below
	   a laptop it goes back to even thirds and the seventh tile takes the
	   short row on its own, which is fine at this size. */
	.sh-tile-grid--7 { grid-template-columns: repeat(3, 1fr); }
	.sh-tile-grid--7 > *,
	.sh-tile-grid--7 > :nth-child(n+5) { grid-column: auto; }
	.sh-perk-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-lg); }
	.sh-team-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	.sh-timeline-row { grid-template-columns: minmax(0, 1fr) 96px minmax(0, 1fr); }
	.sh-timeline-media img { max-width: 250px; }
	.sh-difference { min-height: 0; border-radius: 0 120px 0 120px; }
	.sh-value-grid { grid-template-columns: 1fr; }
	.sh-benefit-grid { grid-template-columns: 1fr; }
	.sh-trust { grid-template-columns: 1fr 1fr; }
	.sh-filter-bar { grid-template-columns: repeat(2, 1fr); }
	.sh-contact-layout { grid-template-columns: minmax(0, 1fr); }
	.sh-feature-row { grid-template-columns: minmax(0, 1fr); gap: var(--space-lg); }
	.sh-feature-row:nth-child(even) .media { order: 0; }
	.sh-feature-rows { gap: var(--space-2xl); }
	.sh-listing-hero-grid { grid-template-columns: minmax(0, 1fr); align-items: start; }
	.sh-listing-hero-search { max-width: 560px; }
}

@media (max-width: 980px) {
	/* Booking sidebar drops below the content and the sticky bar takes over.
	   Nothing is pinned and nothing is height-capped here: on a phone the panel
	   is simply the next thing down the page, and the bottom bar is what keeps
	   the price and the action reachable. */
	.sh-detail-layout { grid-template-columns: minmax(0, 1fr); gap: var(--space-lg); }
	.sh-detail-side { position: static; }
	.sh-booking-panel { position: static; max-height: none; overflow: visible; }
	.sh-mobile-book { display: flex; }
	body.sh-listing { padding-bottom: 84px; }
	.sh-anchor-nav { top: 70px; }
	.sh-checkout-layout { grid-template-columns: minmax(0, 1fr); }
	.sh-summary-card { position: static; order: -1; }
	.sh-split { grid-template-columns: 1fr; gap: var(--space-lg); }

	/* ------------------------------------------------ /rentals/ on a phone
	   The map stops being a column and becomes a view you switch to, so the
	   results keep the full width and nothing is squeezed into a strip. The
	   band stays sticky and stays inside the viewport: it scrolls sideways
	   within itself rather than pushing the page wider (the no-overflow
	   guarantee at 375px). */
	.sh-results-layout { grid-template-columns: minmax(0, 1fr); gap: var(--space-lg); }
	.sh-results-col .sh-grid { grid-template-columns: minmax(0, 1fr); }
	.sh-map-col {
		display: none;
		position: static;
		height: 62vh;
		min-height: 340px;
	}
	body.sh-map-open .sh-map-col { display: block; }
	body.sh-map-open .sh-results-col { display: none; }
	/* The band scrolls sideways within itself on a phone, which keeps the page
	   at 375px, but the Map switch is the one control that must never scroll
	   out of reach. Sticky to the right edge of that scroller, on its own solid
	   maroon so the fields pass underneath it cleanly. */
	/* The fade behind the sticky Map switch is the band's own colour, so it
	   follows the band to coral (round 4, fix 4) rather than leaving a maroon
	   smear across it. */
	.sh-map-toggle {
		display: inline-flex;
		position: sticky;
		right: 0;
		flex-shrink: 0;
		margin-left: auto;
		box-shadow: -14px 0 14px 6px var(--coral);
	}
	.sh-map-toggle[aria-pressed="true"] {
		box-shadow: -14px 0 14px 6px var(--coral);
	}
	.sh-filter-band { top: 70px; }
	.sh-filter-band-inner {
		flex-wrap: nowrap;
		overflow-x: auto;
		scrollbar-width: none;
		padding: 12px var(--wrap-pad-wide);
		gap: 10px;
	}
	.sh-filter-band-inner::-webkit-scrollbar { display: none; }
	.sh-filter-band-inner .sh-field { flex: 0 0 150px; }
	.sh-band-count { display: none; }
	.sh-band-spacer { display: none; }
	.sh-filter-drawer-inner { max-width: none; max-height: min(58vh, 480px); }
}

@media (max-width: 760px) {
	/* ROUND 6: on a phone the hero is shorter again and there is no video at
	   all (chrome.js will not promote the poster below 900px), so this is a
	   photograph with type over it and nothing more. */
	.sh-hero { min-height: 420px; padding: var(--space-xl) 0; border-radius: 0 0 140px 0; }
	.sh-hero h1 { max-width: 100%; }
	.sh-hero-sub { max-width: 100%; margin-bottom: var(--space-md); }
	/* On a phone the bar stacks: one segment per row, rules become the dividing
	   lines between rows. Nothing is set in a fixed width, so the 375px
	   no-overflow guarantee holds. */
	.sh-search-bar { grid-template-columns: minmax(0, 1fr); }
	.sh-seg + .sh-seg::before { display: none; }
	.sh-seg + .sh-seg { border-top: 1px solid #E4E3E0; }
	.sh-seg:nth-child(n + 4) { border-top: 1px solid #E4E3E0; }

	.sh-tile-grid { grid-template-columns: repeat(2, 1fr); }
	.sh-tile-grid--7 { grid-template-columns: repeat(2, 1fr); }

	/* The date picker on a phone: the two months STACK rather than sitting
	   side by side, because side by side at 375px cuts the second one in half.
	   Both are still reachable in one scroll, so you can still see your arrival
	   while choosing a departure in the following month, which is the whole
	   point of showing two. The popover gets a height cap and scrolls, and the
	   footer stays put so Done is always reachable. */
	.sh-range-pop { max-width: calc(100vw - 24px); max-height: 74vh; display: flex; flex-direction: column; }
	.sh-range-months { flex-direction: column; gap: var(--space-md); overflow-y: auto; }
	.sh-range-month { min-width: 0; }
	.sh-range-foot { flex-wrap: wrap; gap: var(--space-xs); }
	/* Proper tap targets on the day cells. */
	.sh-range-month .day { font-size: 0.95rem; }
	/* ROUND 6 sections on a phone. Every one of them is a single column, and
	   the big radii come down to something that still reads as a curve at
	   375px rather than eating half the band. */
	.sh-perk-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-xl); }
	.sh-perk-media { max-width: 320px; }
	.sh-nobs { padding: var(--space-2xl) 0; }
	.sh-difference { border-radius: 0 80px 0 80px; padding: var(--space-2xl) 0; }
	.sh-difference-copy h2 { max-width: 100%; }
	/* The scrim turns vertical on a phone. A left-weighted gradient across a
	   375px band darkens the whole thing and the photograph stops being a
	   photograph; top to bottom lets the picture read at the top and puts the
	   weight under the copy, where it is needed. */
	.sh-difference::after {
		background: linear-gradient(178deg, rgba(22,18,13,.24) 0%, rgba(22,18,13,.52) 34%, rgba(22,18,13,.80) 72%, rgba(22,18,13,.86) 100%);
	}
	.sh-section.sh-band-warm.sh-types { border-radius: 0 120px 0 0; }
	/* On a phone the centre rule moves to the left edge and every row becomes
	   one column: photograph, then card, same order all the way down. A
	   two-sided timeline at 375px is just two narrow columns of nothing. */
	.sh-timeline { padding-left: 42px; gap: var(--space-xl); }
	.sh-timeline::before { left: 13px; margin-left: 0; top: 30px; bottom: 30px; }
	.sh-timeline-row { grid-template-columns: minmax(0, 1fr); gap: var(--space-md); }
	.sh-timeline-row::before { left: -29px; top: 30px; margin-top: 0; }
	.sh-timeline-card,
	.sh-timeline-row:nth-child(even) .sh-timeline-card { grid-column: 1; grid-row: 2; }
	/* Single column: the photograph sits under its card, so it goes back to
	   filling the width rather than leaning at a spine that is no longer beside it. */
	.sh-timeline-media,
	.sh-timeline-row:nth-child(even) .sh-timeline-media { justify-content: flex-start; }
	/* Single column, and the spine runs down the left, so every point faces it. */
	.sh-timeline-media img,
	.sh-timeline-row:nth-child(even) .sh-timeline-media img { border-radius: 50% 50% 50% 0; }
	/* Stacked rows, so the picture sits above its copy: the point goes to the
	   bottom and stays there rather than pointing at nothing sideways. */
	.sh-feature-row .media,
	.sh-feature-row:nth-child(even) .media { border-radius: var(--r-hero) var(--r-hero) var(--r-hero) 0; }
	.sh-timeline-media,
	.sh-timeline-row:nth-child(even) .sh-timeline-media { grid-column: 1; grid-row: 1; }
	.sh-timeline-media img { max-width: 210px; margin: 0; }
	.sh-timeline-card { padding: var(--space-lg) var(--space-md); }
	.sh-team-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-sm); }
	.sh-team-caption { padding: var(--space-xl) var(--space-xs) var(--space-xs); }
	.sh-team-name { font-size: 1.05rem; }
	.sh-featured { grid-template-columns: 1fr; }
	.sh-featured > *, .sh-featured > .span-wide, .sh-browse-tile { grid-column: 1 / -1; }
	.sh-featured > .span-wide .sh-card-media { aspect-ratio: 4 / 3; }
	.sh-browse-tile { min-height: 160px; }
	.sh-grid { grid-template-columns: 1fr; gap: var(--sh-gap-row); }
	.sh-post-grid, .sh-activity-grid, .sh-dest-grid { grid-template-columns: 1fr; }
	.sh-trust { grid-template-columns: 1fr; padding: var(--space-md); }
	.sh-filter-bar { grid-template-columns: 1fr; padding: var(--space-md) var(--space-sm); }
	.sh-filter-drawer { width: calc(100vw - 24px); max-height: 72vh; }
	.sh-contact-form-card { padding: var(--space-lg) var(--space-md); }

	/* Find your ideal stay on a phone (round 5, fix 2): the copy first, then
	   the photograph under it, still flush to the band's bottom and left edges
	   with the arch on its top right, and stopping short of the right edge so
	   the arch reads against the band. */
	.sh-ideal { grid-template-columns: minmax(0, 1fr); min-height: 0; }
	.sh-ideal-copy { order: -1; padding: var(--space-2xl) var(--wrap-pad) var(--space-xl); }
	.sh-ideal-copy p { max-width: none; }
	.sh-ideal-media { min-height: 0; aspect-ratio: 4 / 3; margin-right: 10vw; }
	.sh-page-hero { min-height: 380px; padding: var(--space-2xl) 0 var(--space-xl); }
	/* Vertical only on a phone: a left-weighted wash across 375px darkens the
	   whole photograph. */
	.sh-page-hero::after {
		background: linear-gradient(180deg, rgba(22,18,13,.40) 0%, rgba(22,18,13,.34) 30%, rgba(22,18,13,.58) 72%, rgba(22,18,13,.74) 100%);
	}
	.sh-feature-row .media { aspect-ratio: 16 / 11; }
	/* The gallery arrows are hover-revealed on a mouse; on touch there is no
	   hover, so they are simply always there and sized as tap targets. */
	.sh-gal-btn { display: inline-flex; width: 40px; height: 40px; }
	.sh-gal-dots { display: flex; }

	.sh-gallery { grid-template-columns: 1fr; }
	.sh-gallery-side { grid-template-rows: none; grid-template-columns: 1fr 1fr; }
	.sh-gallery-thumb { aspect-ratio: 4 / 3; }
	.sh-detail-section { padding: var(--space-lg) 0; }
	.sh-spec-row { gap: var(--space-md); }
	.sh-cal-track .month { flex: 0 0 min(300px, 82vw); }
	.sh-amen-groups { grid-template-columns: 1fr; }
	.sh-reviews { gap: var(--space-sm); }
	.sh-review { flex: 0 0 84vw; padding: var(--space-md) var(--space-sm); }


	/* Every control reaches the 44px minimum tap target on phones. */
	.sh-cal-nav button,
	.sh-carousel-nav button { width: 44px; height: 44px; }
	.sh-save { width: 44px; height: 44px; }
	/* Read more / Show all amenities are text links, so they need the height
	   adding as padding rather than a box. */
	.sh-readmore { padding: 10px 0 13px; }
	.sh-share-btn { min-height: 44px; }

	.sh-search-form-row { padding-left: 16px; }
	.sh-search-form .sh-btn { padding: 12px 20px; min-height: 48px; }
	.sh-article-head { padding-top: var(--space-xl); }
	.sh-article-hero-frame { aspect-ratio: 4 / 3; }
	.sh-article-hero .sh-wrap { padding: 0; }
	.sh-article-hero-frame { border-radius: 0 var(--r-hero) 0 0; }
	.sh-article-hero figcaption { padding: 0 var(--wrap-pad); }
	.sh-article-body { font-size: 1.0625rem; line-height: 1.7; }

	#sh-track-panel { right: 12px; bottom: 12px; }
	body.sh-listing #sh-track-panel { bottom: 88px; }
}

/* ------------------------------------------------- help tip in a price line
   The question mark beside the refundable damage deposit. Hover or keyboard
   focus shows the detail, so the summary line stays short. Pure CSS: no
   script, and it still reads correctly to a screen reader through aria-label
   on the trigger. */
.sh-help {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 16px;
	height: 16px;
	margin-left: 4px;
	border-radius: 50%;
	background: var(--stone, #F2F0EB);
	color: var(--dark-orange, #5C0E07);
	font-size: 11px;
	font-weight: 600;
	line-height: 1;
	cursor: help;
	position: relative;
	vertical-align: middle;
}
.sh-help:focus-visible { outline: 2px solid var(--dark-orange, #5C0E07); outline-offset: 2px; }

.sh-help::after {
	content: attr(data-tip);
	/* Below the line, not above it. The deposit is the last row in the summary,
	   so downwards covers empty card rather than sitting over the total, which
	   is the one number a guest is checking when they read this. */
	position: absolute;
	top: calc(100% + 8px);
	right: -6px;
	z-index: 20;
	width: max-content;
	max-width: 260px;
	padding: 9px 13px;
	border-radius: 10px;
	background: var(--dark-orange, #5C0E07);
	color: #fff;
	font-size: 13px;
	font-weight: 400;
	line-height: 1.35;
	text-align: left;
	white-space: normal;
	opacity: 0;
	visibility: hidden;
	transition: opacity .12s ease;
	pointer-events: none;
}
.sh-help:hover::after,
.sh-help:focus::after,
.sh-help:focus-visible::after { opacity: 1; visibility: visible; }

/* On a narrow screen the tip would run off the edge, so pin it to the panel. */
@media (max-width: 560px) {
	.sh-help::after { right: 0; max-width: min(260px, calc(100vw - 48px)); }
}

/* ------------------------------------------------------ marketing opt-in
   A checkbox, laid out so the label is the tap target and the text wraps
   under itself rather than under the box. */
.sh-optin {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	margin: 14px 0 4px;
	cursor: pointer;
	font-size: 14px;
	line-height: 1.45;
	color: var(--dark-orange, #5C0E07);
}
.sh-optin input[type="checkbox"] {
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	margin: 1px 0 0;
	accent-color: var(--dark-orange, #5C0E07);
	cursor: pointer;
}
.sh-optin span { flex: 1 1 auto; }

/* The honeypot. Off screen rather than display:none, because some bots skip
   fields that are explicitly hidden, and this one is meant to be filled in. */
.sh-hp {
	position: absolute !important;
	left: -9999px !important;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* A one-line sign-off CTA: the line and its button sit together and centred,
   and the button is sized by its own text rather than stretching the band. */
.sh-cta-line { text-align: center; margin: 0 auto var(--space-lg); max-width: 46ch; }
.sh-cta-line + .elementor-widget-button,
.sh-cta-line + p { text-align: center; }
.sh-band-warm .sh-btn-acid { display: inline-flex; width: auto; }

/* ------------------------------------------------------------ discount code
   Folded away behind a link, because most guests do not have one and an empty
   box on a checkout invites people to go looking for a code instead of booking. */
.sh-coupon { margin-top: 14px; padding-top: 12px; border-top: 1px solid rgba(92,14,7,.1); }
.sh-coupon-toggle {
	background: none; border: 0; padding: 0; cursor: pointer;
	font: inherit; font-size: 14px; color: var(--maroon);
	text-decoration: underline; text-underline-offset: 3px;
}
.sh-coupon-row { display: flex; gap: 8px; align-items: center; }
.sh-coupon-row input { flex: 1 1 auto; min-width: 0; text-transform: uppercase; }
.sh-coupon-row .sh-btn { flex: 0 0 auto; }
.sh-coupon-msg { margin: 8px 0 0; font-size: 13px; color: var(--maroon); }
.sh-coupon-msg.is-ok { color: #1b6b3a; font-weight: 600; }
.sh-quote-line.is-discount { color: #1b6b3a; font-weight: 600; }
