/**
 * Vinh Local Guide — layout CSS.
 *
 * Colors, typography and button styling come from theme.json. This file
 * is the single source of truth for section WIDTH — every section's
 * visible content uses .vlg-container (1240px) or .vlg-text-container
 * (760px), applied directly by this stylesheet. WordPress's per-block
 * "constrained" layout type is deliberately NOT used for width control
 * inside sections: a nested constrained Group without its own explicit
 * contentSize silently falls back to theme.json's global contentSize
 * (760px) regardless of its parent's width, which was the root cause of
 * sections collapsing to a narrow column with dead space beside them.
 */

:root {
	--vlg-container: 1240px;
	--vlg-text-width: 760px;
	/* Desktop-only (was 92px originally, 104px after one earlier round)
	   to fit the larger boutique-hotel-style logo below without cramping
	   it - every scroll-margin-top / sticky offset calculation elsewhere
	   already reads this variable, so they stay correct automatically.
	   Mobile is untouched. */
	--vlg-header-height: 116px;
	--vlg-header-height-mobile: 100px;
}

/* -----------------------------------------------------------------------
 * Global container system
 * --------------------------------------------------------------------- */

.vlg-container {
	width: min(100% - 32px, var(--vlg-container));
	margin-inline: auto;
}

@media (min-width: 390px) {
	.vlg-container {
		width: min(100% - 40px, var(--vlg-container));
	}
}

@media (min-width: 768px) {
	.vlg-container {
		width: min(100% - 40px, var(--vlg-container));
	}
}

@media (min-width: 1024px) {
	.vlg-container {
		width: min(100% - 48px, var(--vlg-container));
	}
}

.vlg-text-container {
	width: min(100% - 32px, var(--vlg-text-width));
	margin-inline: auto;
}

/* -----------------------------------------------------------------------
 * Section padding scale
 * Desktop (>=1024px): 72-88px · Tablet (768-1023px): 60-76px ·
 * Mobile (<768px): 48-56px. Applied to every major full-width section.
 * --------------------------------------------------------------------- */

.vlg-section {
	padding-top: clamp(48px, 7vw, 56px);
	padding-bottom: clamp(48px, 7vw, 56px);
}

@media (min-width: 768px) {
	.vlg-section {
		padding-top: clamp(60px, 5vw, 76px);
		padding-bottom: clamp(60px, 5vw, 76px);
	}
}

@media (min-width: 1024px) {
	.vlg-section {
		padding-top: clamp(72px, 4.5vw, 88px);
		padding-bottom: clamp(72px, 4.5vw, 88px);
	}
}

.vlg-section--tight {
	padding-top: clamp(36px, 4.5vw, 44px);
	padding-bottom: clamp(36px, 4.5vw, 44px);
}

@media (min-width: 768px) {
	.vlg-section--tight {
		padding-top: clamp(56px, 4vw, 64px);
		padding-bottom: clamp(56px, 4vw, 64px);
	}
}

@media (min-width: 1024px) {
	.vlg-section--tight {
		padding-top: clamp(64px, 4vw, 72px);
		padding-bottom: clamp(64px, 4vw, 72px);
	}
}

/* Home only, mobile only: the tour-grid section's bottom padding plus
   the gallery section's top padding used to stack to ~100px+ of empty
   color-change space around the "See all tours" button. Trimmed so the
   two together land in the 40-52px range the button needs to not feel
   orphaned, without touching the shared .vlg-section token everywhere
   else on the site. */
@media (max-width: 899px) {
	.vlg-section--home-tours-bottom {
		padding-bottom: 24px;
	}

	.vlg-section--home-gallery-top {
		padding-top: 24px;
	}
}

/* -----------------------------------------------------------------------
 * Global typography discipline — a hard mobile ceiling so no normal
 * paragraph, heading or button can ever render oversized on a phone,
 * regardless of what a fluid clamp() elsewhere would compute. Desktop
 * sizing comes from theme.json (H1/H2/H3 tokens, body, "large" intro).
 * --------------------------------------------------------------------- */

@media (max-width: 899px) {
	h1 {
		font-size: clamp(40px, 8vw, 46px);
		line-height: 1.06;
	}

	h2 {
		font-size: clamp(30px, 7vw, 36px);
		line-height: 1.12;
	}

	h3 {
		font-size: clamp(24px, 6vw, 28px);
		line-height: 1.15;
	}

	body,
	p {
		font-size: 16px;
		line-height: 1.6;
	}

	.vlg-lead {
		font-size: clamp(16px, 3vw, 17px) !important;
		line-height: 1.55;
	}

	.vlg-eyebrow {
		font-size: 11px;
	}

	.wp-block-button__link {
		font-size: 16px;
	}
}

/* Buttons: one consistent pill shape/height everywhere, compact on
 * mobile — full width is the exception (hero/mobile-nav opt in
 * explicitly via .vlg-full-width-mobile), not the default. */
.wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 48px;
	border-radius: 999px;
	box-sizing: border-box;
}

@media (max-width: 899px) {
	.wp-block-button__link {
		min-height: 51px;
	}
}

@media (min-width: 900px) {
	.wp-block-button__link {
		padding: 0 26px !important;
		font-size: 15px;
	}
}

@media (max-width: 899px) {
	.wp-block-button:not(.vlg-full-width-mobile) {
		max-width: 280px;
	}

	.wp-block-button:not(.vlg-full-width-mobile) .wp-block-button__link {
		padding: 0 24px !important;
	}
}

/* -----------------------------------------------------------------------
 * Header — dark, sticky, fixed height, real logo, explicit breakpoint
 * --------------------------------------------------------------------- */

.vlg-site-header {
	position: sticky;
	top: 0;
	z-index: 100;
	box-shadow: 0 2px 12px rgba(13, 43, 33, 0.18);
}

.vlg-site-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	min-height: var(--vlg-header-height-mobile);
}

@media (min-width: 900px) {
	.vlg-site-header__inner {
		min-height: var(--vlg-header-height);
	}
}

/* Hard safety net: the header must never grow taller than its target
   height and must never scroll horizontally, even if something fails
   to hide correctly (e.g. the desktop CTA). This cannot fix a
   mis-hidden element but guarantees it cannot blow up the header
   height or leak outside the viewport. */
.vlg-site-header__inner {
	flex-wrap: nowrap;
	max-height: var(--vlg-header-height-mobile);
	overflow: hidden;
}

@media (min-width: 900px) {
	.vlg-site-header__inner {
		max-height: var(--vlg-header-height);
	}
}

.vlg-site-brand {
	display: flex;
	align-items: center;
	flex-shrink: 0;
}

/* The real logo file is a square badge (icon + wordmark stacked
   inside a 1:1 canvas), not a wide horizontal lockup. Sizing it by
   WIDTH alone (as a previous pass did, at 145/175px) makes it just as
   TALL, which silently forced the header to grow to ~184px on desktop
   to fit it (no clipping there) - and only "looked" fine on mobile
   because the safety net above was quietly cropping ~30px off the top
   and bottom of an oversized logo. Sizing by HEIGHT instead keeps the
   header genuinely compact everywhere. */
.vlg-site-logo img {
	display: block;
	width: auto;
	height: 52px;
}

@media (min-width: 900px) {
	/* Boutique-hotel-scale mark: clearly identifiable without a bulky
	   header - height-based sizing (not width) keeps it crisp since the
	   source PNG's intrinsic resolution (300x300, the WordPress "medium"
	   size already used here) comfortably covers this size, so it is
	   never upscaled/blurred. --vlg-header-height above grew to match
	   so the logo keeps generous breathing room above and below rather
	   than crowding the header's edges. */
	.vlg-site-logo img {
		height: 92px;
		width: auto;
	}

	/* <figure> defaults to display:block, so the extra height WordPress
	   gives the image wrapper (measured live: 101px for a 92px-tall
	   logo) was never actually centered around the image the way
	   .vlg-site-logo's own flex/align-items:center implied - the image
	   sat flush at the figure's top instead, 4px above true center.
	   Flexing the figure/link too closes that last gap. Scoped to
	   desktop only: the mobile crop-zoom technique further down in this
	   file already sets its own explicit display/margin on these same
	   elements for its own purposes and must not be touched. */
	.vlg-site-logo figure,
	.vlg-site-logo a {
		display: flex;
		align-items: center;
		margin: 0;
	}

	/* Pre-existing bug, confirmed live and present even before the logo
	   was enlarged: WordPress's own default block-gap styling
	   (`:where(.is-layout-flow) > * { margin-block: 1.5rem 0 }`, applied
	   because .vlg-site-header__inner carries the "is-layout-flow"
	   marker class) was adding a silent 24px margin-top to the nav and
	   the CTA button - but not to .vlg-site-brand, which resets its own
	   margin - so flex's align-items:center was centering their taller
	   (margin-included) box instead of their visible content, visibly
	   sitting 12px lower than the logo. */
	.vlg-primary-nav,
	.vlg-header-cta {
		margin-top: 0;
	}
}

/* Mobile only: the source PNG is a square 300x300 canvas but the actual
   visible mark (icon + wordmark) only fills a ~260x153px band vertically
   centered inside it - large transparent padding above and below. Sizing
   by height alone (as above) scales that padding too, so the logo reads
   as tiny even at a "reasonable" height. Fix: render the image at a
   larger intrinsic size, then use an overflow:hidden crop window sized
   to the visible mark (plus a safety margin on every side) to zoom into
   it - visually bigger without touching the source asset. Desktop is
   untouched.

   Root cause of the top still being clipped in the last two passes,
   confirmed live via getComputedStyle: .vlg-site-logo is a WordPress
   block group with layout:flex, which WordPress itself styles via
   `.wp-block-group.is-layout-flex{display:flex;align-items:center}` -
   a two-class selector that beats this file's single-class
   `.vlg-site-logo{display:block}` on specificity alone, regardless of
   source order. display:flex + align-items:center was never overridden,
   so the (taller) figure inside was being vertically CENTERED in the
   84px box instead of sitting flush at its top - centering an oversized
   child pushes its top edge above the box, and overflow:hidden clipped
   exactly that pushed-up portion, eating into the logo itself. */
@media (max-width: 899px) {
	.vlg-site-logo {
		display: block !important;
		width: 125px;
		height: 84px;
		overflow: hidden;
	}

	.vlg-site-logo figure,
	.vlg-site-logo a {
		display: block;
		margin: 0;
	}

	.vlg-site-logo img {
		width: 130px;
		height: 130px;
		max-width: none;
		margin: -17px 0 0 -4px;
	}
}

.vlg-primary-nav {
	gap: 2.25rem;
	flex-grow: 1;
	justify-content: center;
}

.vlg-primary-nav a,
.vlg-primary-nav .wp-block-navigation-item__label {
	color: var(--wp--preset--color--ivory-white);
	font-family: var(--wp--preset--font-family--body);
	font-size: 1rem;
	font-weight: 600;
	letter-spacing: 0.02em;
}

.vlg-primary-nav a:hover {
	color: var(--wp--preset--color--gold);
}

/* Active-page indicator - a quiet gold text color plus a thin animated
   underline (grown in with a transform, not a layout-affecting width/
   text-decoration change) rather than a solid block of color, so the
   current page reads as a refined detail instead of a heavy badge.
   Live-verified this needed its own JS: none of these nav links
   reference a real WP Page/Post (every one is a "custom" URL link, see
   header.html/footer.html), so WordPress's automatic aria-current
   detection never actually ran for them - see markActiveLink() in
   assets/js/mobile-menu.js, which now covers this nav and the footer
   nav too, not just the mobile overlay. */
.vlg-primary-nav a {
	position: relative;
	display: inline-block;
}

.vlg-primary-nav a::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: -6px;
	height: 1.5px;
	background-color: var(--wp--preset--color--gold);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 0.25s ease;
}

.vlg-primary-nav a:hover::after,
.vlg-primary-nav a[aria-current="page"]::after {
	transform: scaleX(1);
}

/* The visible link text sits in a child
   <span class="wp-block-navigation-item__label">, which carries its own
   explicit color (see .vlg-primary-nav a, .vlg-primary-nav
   .wp-block-navigation-item__label above) - confirmed live that setting
   color only on the <a> itself does nothing, since that span's own
   declared color always wins over inheriting from its parent. */
.vlg-primary-nav a[aria-current="page"],
.vlg-primary-nav a[aria-current="page"] .wp-block-navigation-item__label,
.vlg-footer-nav a[aria-current="page"] {
	color: var(--wp--preset--color--gold);
}

@media (prefers-reduced-motion: reduce) {
	.vlg-primary-nav a::after {
		transition: none;
	}
}

.vlg-header-cta {
	flex-shrink: 0;
}

.vlg-header-cta .wp-block-button__link {
	white-space: nowrap;
}

/* Desktop nav + CTA are visible only >=900px; the custom hamburger/
   overlay (below) takes over entirely below that — see §MOBILE MENU.
   .vlg-burger is mobile-first hidden here (display:none is the only
   rule for it outside of @media(max-width:899px) — see that block for
   why: this used to be split as an unconditional "display:flex" base
   rule further down the file plus a min-width:900px override up here,
   and because both had equal specificity, whichever was LATER in the
   file won at every width — the unconditional rule was declared after
   this override, so the hamburger stayed visible on desktop too. */
@media (min-width: 900px) {
	.vlg-burger {
		display: none !important;
	}
}

@media (max-width: 899px) {
	.vlg-header-cta,
	.vlg-primary-nav {
		display: none !important;
	}
}

/* While the mobile overlay is open, the normal header row (logo +
   hamburger) must not stay visible underneath it: hide it outright
   instead of relying on the overlay's opacity/z-index to cover it, so
   there is never a duplicate logo or a duplicate hamburger/close pair. */
@media (max-width: 899px) {
	body.vlg-menu-open .vlg-site-header__inner {
		display: none;
	}
}

/* Belt-and-suspenders: forcibly hide WordPress core's own Navigation
   responsive/overlay controls on mobile no matter what, even if
   overlayMenu:"never" is ever ignored by the installed Gutenberg
   version. Without this, a leftover core hamburger/close pair could
   render alongside the custom .vlg-burger / .vlg-mobile-nav below. */
@media (max-width: 899px) {
	.wp-block-navigation__responsive-container-open,
	.wp-block-navigation__responsive-container-close,
	.wp-block-navigation__responsive-container:not(.vlg-mobile-nav) {
		display: none !important;
	}
}

/* Defensive reset: WordPress's Navigation block renders a <ul>/<li>
   list internally: make sure no bullet markers ever show, on desktop
   or in the footer nav. */
.wp-block-navigation ul,
.wp-block-navigation li,
.vlg-mobile-nav__links {
	list-style: none;
	margin: 0;
	padding: 0;
}

/* -----------------------------------------------------------------------
 * Mobile menu — hamburger button + full-screen overlay (<900px only).
 * Fully custom (see parts/header.html + assets/js/mobile-menu.js):
 * WordPress core's own Navigation overlay is disabled on mobile because
 * relying on it produced an unreliable hamburger icon, a duplicated
 * hamburger+close state, bullets on links and the desktop CTA bleeding
 * into the overlay.
 * --------------------------------------------------------------------- */

.vlg-burger {
	/* Reset native button chrome: real Android/iOS browsers can render
	   default button padding/background/border here even when a desktop
	   emulator does not, which is enough to visually break a 3-bar icon
	   down to what looks like a single flat line. */
	-webkit-appearance: none;
	appearance: none;
	-webkit-tap-highlight-color: transparent;
	/* Mobile-first: hidden by default, only ever shown below 900px (see
	   the max-width:899px rule right after this one). Never rely on a
	   min-width:900px override alone to hide it — see the note above
	   §MOBILE MENU for the cascade-order bug that caused. */
	display: none;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 6px;
	width: 32px;
	height: 32px;
	min-width: 32px;
	min-height: 32px;
	padding: 0;
	margin: 0;
	background: transparent;
	border: 0;
	outline: 0;
	flex-shrink: 0;
	cursor: pointer;
}

@media (max-width: 899px) {
	.vlg-burger {
		display: flex;
	}
}

.vlg-burger__bar {
	display: block;
	width: 26px;
	height: 2px;
	flex-shrink: 0;
	border-radius: 2px;
	background-color: var(--wp--preset--color--ivory-white, #fffdf8);
}

.vlg-mobile-nav {
	/* Hard-pinned to the actual viewport, independent of any ancestor
	   (it is now a sibling of <header>, not nested inside it - see the
	   comment in parts/header.html). The !important flags and explicit
	   margin/transform resets are deliberate: this element must never
	   be pushed down or clipped by anything else on the page, on any
	   real device, leaving a strip of the hero/header visible above it. */
	position: fixed !important;
	inset: 0 !important;
	top: 0 !important;
	right: 0 !important;
	bottom: 0 !important;
	left: 0 !important;
	width: 100% !important;
	height: 100dvh !important;
	margin: 0 !important;
	transform: none !important;
	z-index: 2147483647;
	display: flex;
	flex-direction: column;
	background-color: var(--wp--preset--color--dark-green, #0d2b21);
	/* Padding insets the LOGO/CLOSE/links/CTA content only - the
	   background-color above still fills the full box edge-to-edge
	   (padding never excludes background-color), so this cannot create
	   a visible gap around the overlay. */
	padding: 20px;
	box-sizing: border-box;
	overflow-y: auto;
	overflow-x: hidden;
	/* Only the overlay's own content may scroll; "contain" stops that
	   scroll from chaining through to the page pinned behind it. */
	overscroll-behavior: contain;
	-webkit-overflow-scrolling: touch;
}

.vlg-mobile-nav[hidden] {
	display: none;
}

.vlg-mobile-nav__top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-shrink: 0;
}

/* Same crop-zoom technique as .vlg-site-logo (see the comment there) but
   larger and more generous, since the open full-screen menu has room to
   let the logo read as a premium, clearly legible mark rather than a
   small header badge. */
.vlg-mobile-nav__logo {
	display: block;
	width: 160px;
	height: 110px;
	overflow: hidden;
}

.vlg-mobile-nav__logo img {
	display: block;
	width: 170px;
	height: 170px;
	max-width: none;
	margin: -23px 0 0 -6px;
}

.vlg-mobile-nav__close {
	-webkit-appearance: none;
	appearance: none;
	-webkit-tap-highlight-color: transparent;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	min-width: 40px;
	min-height: 40px;
	padding: 0;
	margin: 0;
	background: transparent;
	border: 0;
	outline: 0;
	color: var(--wp--preset--color--ivory-white, #fffdf8);
	font-size: 2rem;
	line-height: 1;
	cursor: pointer;
}

.vlg-mobile-nav__links {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 26px;
	flex-grow: 1;
	padding: 32px 0;
}

.vlg-mobile-nav__links a {
	-webkit-tap-highlight-color: transparent;
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: clamp(30px, 8vw, 34px);
	color: var(--wp--preset--color--ivory-white, #fffdf8);
	text-decoration: none;
	white-space: nowrap;
}

.vlg-mobile-nav__links a[aria-current="page"] {
	color: var(--wp--preset--color--gold, #d6aa52);
}

.vlg-mobile-nav__cta {
	-webkit-tap-highlight-color: transparent;
	box-sizing: border-box;
	display: block;
	flex-shrink: 0;
	width: 100%;
	max-width: 300px;
	margin: 0 auto 12px;
	padding: 14px 24px;
	border-radius: 999px;
	text-align: center;
	font-family: var(--wp--preset--font-family--body);
	font-weight: 700;
	font-size: 16px;
	text-decoration: none;
	background-color: var(--wp--preset--color--gold, #d6aa52);
	color: var(--wp--preset--color--dark-green, #0d2b21);
}

/* Body-scroll lock while the mobile menu overlay is open. overflow:
   hidden on body alone does not reliably stop touch-scroll chaining
   on real mobile browsers (the underlying page can still be dragged
   behind the overlay) - pin body with position:fixed at a negative
   top offset equal to the scroll position at open time (set by
   assets/js/mobile-menu.js), which is the standard robust technique.
   overscroll-behavior:none additionally stops any residual scroll/
   bounce chaining out to the page. */
html.vlg-menu-open,
body.vlg-menu-open {
	overflow: hidden;
	overscroll-behavior: none;
}

body.vlg-menu-open {
	position: fixed;
	left: 0;
	right: 0;
	width: 100%;
}

@media (min-width: 900px) {
	.vlg-mobile-nav {
		display: none !important;
	}
}

/* Remove dead space between the sticky header and whatever follows it,
   at every width (this was mobile-only before, but the same WordPress
   block-gap band was visible on desktop too). Two targets because the
   site has two different page shapes: Home/Tours put a full-screen
   .vlg-hero directly after the header template part (so the gap lands
   on .vlg-hero itself); the other four pages go straight into
   <main class="vlg-page"> (so the gap lands there instead). */
.vlg-site-header {
	margin-bottom: 0 !important;
}

.vlg-page {
	margin-top: 0 !important;
}

.vlg-hero {
	margin-top: 0 !important;
}

/* -----------------------------------------------------------------------
 * Full-screen hero (Home + Tours) — height capped, text scales with
 * viewport WIDTH within sane bounds, never with the (unbounded) height.
 * --------------------------------------------------------------------- */

.vlg-hero {
	position: relative;
	min-height: clamp(620px, 78vh, 860px);
	display: flex;
	align-items: center;
	justify-content: center;
	background-color: var(--wp--preset--color--dark-green);
	background-image: var(--vlg-hero-desktop);
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
	padding: 3rem 0;
	overflow: hidden;
}

.vlg-hero__overlay {
	position: absolute;
	inset: 0;
	background: linear-gradient(
		180deg,
		rgba(13, 43, 33, 0.6) 0%,
		rgba(13, 43, 33, 0.4) 45%,
		rgba(13, 43, 33, 0.8) 100%
	);
	z-index: 0;
}

.vlg-hero__content {
	position: relative;
	z-index: 1;
	width: min(100% - 32px, 620px);
	margin-inline: auto;
	text-align: left;
}

.vlg-hero__title {
	margin-top: 0.5rem;
	line-height: 1.08;
	font-size: clamp(42px, 4vw, 70px) !important;
}

.vlg-hero__lead {
	max-width: 46ch;
	font-size: clamp(18px, 1.4vw, 22px) !important;
}

/* Tours hero (desktop only - the mobile crop is separately, carefully
   tuned further down in its own max-width:899px block and untouched
   here): the photo (vinh_van-...png) has Vinh standing on the LEFT
   third of the frame, the van filling the rest. At every desktop
   width, background-size:cover on this hero's wide, short box always
   fits by WIDTH (the box is proportionally wider than the photo's
   16:9 source), so the full photo width is visible with no horizontal
   crop - meaning the centered .vlg-hero__content (the same block Home
   uses) landed right on top of Vinh instead of beside him, confirmed
   via a live screenshot. Shifting the content block to hug the right
   side puts it over the van/background instead, leaving Vinh fully
   visible and unobstructed on the left. The overlay gets a second,
   diagonal gradient layered under the existing vertical one - lighter
   over Vinh on the left (he stays the valorized subject), darker
   under the text on the right for contrast against the van's pale
   body. */
@media (min-width: 900px) {
	.vlg-hero--tours .vlg-hero__content {
		margin-left: auto;
		margin-right: min(6vw, 90px);
	}

	.vlg-hero--tours .vlg-hero__overlay {
		background:
			linear-gradient(100deg, rgba(13, 43, 33, 0.08) 0%, rgba(13, 43, 33, 0.2) 35%, rgba(13, 43, 33, 0.62) 58%, rgba(13, 43, 33, 0.5) 100%),
			linear-gradient(180deg, rgba(13, 43, 33, 0.35) 0%, rgba(13, 43, 33, 0.2) 45%, rgba(13, 43, 33, 0.65) 100%);
	}
}

.vlg-hero .wp-block-buttons {
	margin-top: 2rem;
	gap: 1rem;
}

/* Home hero buttons: a one-time fade-up on page load (see the mobile
   @media block below for where this is applied) - deliberately a
   plain CSS animation that plays once and stops, never a scroll-
   triggered one. */
@keyframes vlg-hero-buttons-in {
	from {
		opacity: 0;
		transform: translateY(14px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

@media (max-width: 899px) {
	.vlg-hero {
		background-image: var(--vlg-hero-mobile);
		background-position: center 22%;
		min-height: calc(100svh - var(--vlg-header-height-mobile));
	}

	/* Home only: stretch (rather than center) the content block so it
	   can fill the hero's full height - needed for the buttons'
	   margin-top:auto trick just below to have room to push them
	   toward the bottom instead of everything sitting as one compact,
	   vertically-centered unit. Tours has no buttons in its hero and
	   keeps the plain centered layout (.vlg-hero's own align-items:
	   center further up), so its short eyebrow+title+lead block still
	   sits centered rather than clumping at the top with empty space
	   below it. */
	.vlg-hero--home {
		align-items: stretch;
	}

	/* The eyebrow/line/heading/paragraph stay grouped tightly at the
	   top (their own normal margins, untouched here); margin-top:auto
	   on the buttons is what anchors them near the bottom of the hero
	   instead of directly under the paragraph, so the section reads as
	   deliberately composed top-to-bottom rather than one centered
	   clump with dead space above and below it. */
	.vlg-hero__content {
		display: flex;
		flex-direction: column;
		padding-top: clamp(28px, 6vh, 48px);
		padding-bottom: clamp(28px, 6vh, 48px);
	}

	/* Home's buttons sit right above the floating WhatsApp/Zalo pills
	   (fixed at the bottom-right of the viewport). A vh-based reserve
	   here (an earlier attempt) broke on short viewports - the eyebrow/
	   title/lead block's own height barely shrinks with viewport height
	   (only its width changes what wraps), so on a short phone the
	   centered/stretched content could no longer satisfy both "top text
	   at natural size" and "N vh reserved at the bottom" at once, and
	   the buttons ended up sliding down into the floating buttons
	   regardless of the reserved percentage. Fixed pixel values, tuned
	   against the now-smaller buttons below, verified live at both
	   375x812 and 375x667 with no overlap (the two button blocks stay
	   horizontally apart even where they're at a similar height, since
	   these buttons are centered and the floating ones sit further
	   right). */
	.vlg-hero--home .vlg-hero__content {
		padding-top: 20px;
		padding-bottom: 0px;
	}

	/* The Tours hero photo is a wide 16:9 landscape shot. On the same
	   near-full-viewport height as the Home hero, cover only had room
	   to show ~30% of the image's width no matter the position - an
	   inherently over-zoomed crop, not a positioning problem. Shortening
	   the box itself (Tours only, Home's hero height is untouched) is
	   what actually fixes it: at 60vh the visible slice grows to ~43% of
	   the photo's width, enough to keep Vinh, his gesture, the van AND
	   the mountain backdrop in frame together. Compared live against
	   42-45%, 40% was the best-balanced crop: it keeps Vinh's face and
	   expression clearly readable (he is the "personally guided" part
	   of the brand) while still showing the van and the mountains. */
	.vlg-hero--tours {
		min-height: 60vh;
		background-position: 40% center;
		/* Stretch (not flex-start) so .vlg-hero__content fills the whole
		   hero height - needed for the lead paragraph's margin-top:auto
		   trick below, which anchors it flush against the bottom of the
		   box. That's a reliable clear of Vinh's face AND arm on any
		   device aspect ratio; a fixed rem push only worked on some
		   screens and, since it grows the box (a background-image with
		   background-size:cover), was also progressively zooming the
		   photo in on real devices instead of just repositioning text. */
		align-items: stretch;
	}

	.vlg-hero--tours .vlg-hero__content {
		display: flex;
		flex-direction: column;
		padding-top: 4px;
		/* Smaller than the generic hero's inherited bottom padding, on
		   purpose: less reserved space at the bottom gives the lead
		   paragraph's margin-top:auto (below) a little more room to
		   settle lower, clearing more of Vinh's face/torso. */
		padding-bottom: 12px;
	}

	/* Smaller than Home's hero title (which has no photo underneath it
	   competing for space) so the two-line heading fits above Vinh's
	   face instead of dipping into his cap. */
	.vlg-hero--tours .vlg-hero__title {
		font-size: clamp(32px, 7.5vw, 36px) !important;
		line-height: 1.08 !important;
	}

	.vlg-hero--tours .vlg-hero__lead {
		/* margin-top:auto (not a fixed rem) pushes the paragraph all the
		   way down to sit just above the box's own padding-bottom,
		   clearing Vinh's face and arm regardless of title height or
		   device aspect ratio - see the .vlg-hero--tours comment above. */
		margin-top: auto;
	}

	.vlg-hero__content {
		text-align: center;
		width: calc(100% - 40px);
		max-width: 520px;
	}

	.vlg-eyebrow {
		font-size: clamp(11px, 2.6vw, 12px);
	}

	.vlg-hero__title {
		margin-top: 0.75rem;
		margin-bottom: 0.85rem;
		line-height: 1.05 !important;
		font-size: clamp(42px, 9vw, 46px) !important;
	}

	.vlg-hero__lead {
		max-width: none;
		margin-left: auto;
		margin-right: auto;
		line-height: 1.55;
		font-size: clamp(16.5px, 3vw, 17px) !important;
	}

	.vlg-hero .wp-block-buttons {
		flex-direction: column;
		align-items: center;
		gap: 10px;
		/* Pushes the buttons to the bottom of .vlg-hero__content (a
		   stretched flex column, see above) instead of directly under
		   the paragraph, so they read as anchored near the bottom of
		   the hero rather than sitting high up in a centered clump. */
		margin-top: auto;
		padding-top: 1.5rem;
	}

	/* A one-time fade-up on page load for the Home hero buttons only -
	   a load-time CSS animation, not a scroll-triggered one. The site
	   owner previously reported real multi-second scroll freezes caused
	   by continuous scroll-linked effects (an IntersectionObserver
	   fade-up and a box-shadow pulse, both removed); this runs once on
	   paint and then stops for good, so it carries none of that risk. */
	.vlg-hero--home .wp-block-buttons {
		animation: vlg-hero-buttons-in 0.7s ease-out 0.5s both;
	}

	@media (prefers-reduced-motion: reduce) {
		.vlg-hero--home .wp-block-buttons {
			animation: none;
		}
	}

	/* Sized down twice now at the site owner's request - first from
	   80%/290px/52px, then to this fixed, deliberately compact width
	   (matching a hand-drawn reference rectangle) so the buttons read
	   as a tight pill instead of a near-full-width bar, leaving most
	   of the photo readable above them. Fixed px (not a percentage)
	   keeps them exactly this size regardless of viewport width within
	   the mobile range. */
	.vlg-hero .wp-block-buttons .wp-block-button {
		width: 180px;
		max-width: 180px;
	}

	.vlg-hero .wp-block-buttons .wp-block-button__link {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 100%;
		min-height: 44px;
		padding: 0 16px;
		font-size: 15px;
	}

	/* Matches the live reference site's hero: primary (View Tours)
	   stays the standard filled-gold button; secondary (Check
	   Availability) becomes transparent with a gold border and light
	   text, so it reads clearly over the photo without competing with
	   the primary button. Both are already the same width/height/
	   radius via the shared rules above - only the fill changes. */
	.vlg-hero .wp-block-buttons .is-style-vlg-secondary .wp-block-button__link {
		background-color: transparent;
		border: 2px solid var(--wp--preset--color--gold);
		color: var(--wp--preset--color--ivory-white);
	}

	/* The gold rule under the eyebrow is left-aligned by default (see
	   .vlg-eyebrow::after below); on mobile the hero content itself is
	   centered, so without this the line stays pinned to the left of a
	   centered word - visually disconnected from it. */
	.vlg-hero__content .vlg-eyebrow::after {
		margin-inline: auto;
	}
}

/* -----------------------------------------------------------------------
 * Eyebrow labels / leads / page intros
 * --------------------------------------------------------------------- */

/* Small reusable accent for a single highlighted word/phrase inside an
   otherwise normal heading or paragraph (hero title, footer tagline,
   Gallery H1, Contact title, ...), instead of a one-off inline style
   at every place one is needed. */
.vlg-text-gold {
	color: var(--wp--preset--color--gold);
}

.vlg-eyebrow {
	font-family: var(--wp--preset--font-family--body);
	font-size: 0.8rem;
	font-weight: 700;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--wp--preset--color--gold-hover);
	margin-bottom: 0.35rem;
}

/* Premium detail: a thin gold rule under every eyebrow label, aligned
   to the same side as the text (left by default; centered whenever
   the eyebrow itself is center-aligned). */
.vlg-eyebrow::after {
	content: "";
	display: block;
	width: 48px;
	height: 1px;
	margin-top: 0.6rem;
	background-color: var(--wp--preset--color--gold);
}

.vlg-eyebrow.has-text-align-center::after {
	margin-inline: auto;
}

.vlg-lead {
	color: var(--wp--preset--color--secondary-text);
	font-size: var(--wp--preset--font-size--large);
}

/* Used where .vlg-lead sits on a dark-green section (e.g. the Gallery
   page intro) instead of the usual light background - two classes
   beats the single-class rule above regardless of source order, so
   this reliably wins without needing !important. */
.vlg-lead.has-light-sage-color {
	color: var(--wp--preset--color--light-sage);
}

.vlg-page-intro {
	text-align: center;
}

/* Defensive: every intro heading (e.g. "Crafted for curious minds")
   must always wrap safely inside its container, never clip. */
.vlg-page-intro .wp-block-heading {
	max-width: 100%;
	overflow-wrap: normal;
	word-break: normal;
}

/* -----------------------------------------------------------------------
 * Guide intro (Home) / two-column story sections — real CSS grid,
 * independent of WordPress's Columns block width assumptions.
 * --------------------------------------------------------------------- */

.vlg-guide-intro.wp-block-columns {
	display: grid !important;
	grid-template-columns: 1fr 1fr;
	gap: clamp(2.5rem, 6vw, 90px);
	align-items: center;
}

.vlg-guide-intro > .wp-block-column {
	flex-basis: auto !important;
	width: auto !important;
	margin: 0 !important;
}

.vlg-guide-intro img {
	border-radius: 16px;
	max-width: 520px;
	margin-inline: auto;
	border: 1px solid var(--wp--preset--color--dark-green);
	box-shadow: 0 8px 24px rgba(13, 43, 33, 0.14);
}

/* Pre-existing bug found while testing this round's changes at 1024px
   (present on the unmodified live site too, unrelated to anything else
   in this round): with only max-width set and no width, the image
   rendered at a flat 520px regardless of its actual column width -
   .vlg-guide-intro's column is only ~450px wide at 1024px, so the
   image overflowed the container by 70px. width:100% lets it shrink to
   fit a narrower column while max-width:520px above still caps it once
   the column is wide enough. Scoped to desktop only - mobile already
   has its own complete override (width/height/object-fit) below. */
@media (min-width: 900px) {
	.vlg-guide-intro img {
		width: 100%;
	}
}

@media (max-width: 899px) {
	.vlg-guide-intro img {
		width: 100%;
		height: clamp(520px, 82vw, 620px);
		object-fit: cover;
		object-position: center top;
	}
}

.vlg-about-intro.wp-block-columns {
	display: grid !important;
	grid-template-columns: 55% 1fr;
	gap: clamp(2rem, 5vw, 4rem);
	align-items: center;
}

.vlg-about-intro > .wp-block-column {
	flex-basis: auto !important;
	width: auto !important;
	margin: 0 !important;
}

.vlg-about-intro img {
	border-radius: 16px;
	border: 1px solid rgba(214, 170, 82, 0.55);
}

.vlg-about-intro h1 {
	max-width: 16ch;
}

@media (max-width: 781px) {
	.vlg-guide-intro.wp-block-columns,
	.vlg-about-intro.wp-block-columns {
		grid-template-columns: 1fr;
	}

	/* Stacked on mobile, this section should read heading, then Vinh's
	   photo, then the body text, then the button - not all the text
	   first and the photo last. The photo lives in a separate column
	   from the heading/paragraphs/button in the markup, so
	   display:contents lets both columns' children become direct grid
	   items here, reorderable independently of their original column. */
	.vlg-guide-intro > .wp-block-column:first-child {
		display: contents;
	}

	.vlg-guide-intro .vlg-eyebrow {
		order: 1;
	}

	.vlg-guide-intro h2 {
		order: 2;
	}

	.vlg-guide-intro > .wp-block-column:nth-child(2) {
		order: 3;
	}

	.vlg-guide-intro p:not(.vlg-eyebrow) {
		order: 4;
	}

	.vlg-guide-intro .wp-block-buttons {
		order: 5;
		justify-content: center;
		margin-top: 1.5rem;
	}
}

@media (max-width: 899px) {
	.vlg-about-intro img {
		width: 100%;
		max-height: 580px;
		aspect-ratio: 4 / 5;
		object-fit: cover;
		object-position: center top;
	}
}

/* -----------------------------------------------------------------------
 * About Vinh — "Born where mountains meet sea": no confidently-matching
 * extra image exists in the media library for this story, so per spec
 * it becomes a designed text card (not a plain paragraph floating in an
 * empty light-sage band) with a subtle decorative gold rule.
 * --------------------------------------------------------------------- */

.vlg-about-story {
	padding: clamp(2.5rem, 5vw, 3.5rem);
	box-shadow: 0 4px 16px rgba(13, 43, 33, 0.1);
	border-left: 4px solid var(--wp--preset--color--gold);
}

.vlg-about-story__rule {
	width: 48px;
	height: 3px;
	margin-bottom: 1.25rem;
	background-color: var(--wp--preset--color--gold);
	border-radius: 2px;
}

@media (max-width: 899px) {
	.vlg-about-story {
		padding: 2rem 1.5rem;
	}
}

/* -----------------------------------------------------------------------
 * About Vinh — "How Vinh Guides" value cards (Private / Flexible / Local)
 * --------------------------------------------------------------------- */

.vlg-value-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 2rem;
	margin-top: 2.5rem;
	align-items: stretch;
}

/* See .vlg-included-item above for why an explicit height:100% is
   needed on top of the grid's own align-items:stretch, and for the
   margin-top:0 - WordPress's default block-gap styling adds
   margin-top:24px to every card except the first, which on its own
   (even with equal heights) still visibly sits the first card 24px
   higher than the other two - confirmed live. Desktop-only. */
@media (min-width: 900px) {
	.vlg-value-card {
		height: 100%;
		box-sizing: border-box;
		margin-top: 0;
	}
}

.vlg-value-card {
	min-height: 190px;
	display: flex;
	flex-direction: column;
	justify-content: center;
	text-align: center;
	padding: 1.75rem 1.5rem;
	background-color: var(--wp--preset--color--card-background);
	border: 1px solid var(--wp--preset--color--light-border);
	border-radius: 16px;
	/* A quiet resting elevation (no gold side accent) - the hover lift
	   below adds the "raised" feeling on interaction, kept subtle so it
	   never reads as a cartoonish pop. */
	box-shadow: 0 4px 14px rgba(13, 43, 33, 0.08);
	transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.vlg-value-card:hover {
	transform: translateY(-4px);
	box-shadow: 0 12px 28px rgba(13, 43, 33, 0.14);
}

.vlg-value-card__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	flex-shrink: 0;
	margin: 0 auto 1rem;
	color: var(--wp--preset--color--ivory-white);
	background-color: var(--wp--preset--color--gold);
	border-radius: 50%;
	padding: 10px;
	box-shadow: 0 4px 10px rgba(214, 170, 82, 0.35);
}

.vlg-value-card__icon svg {
	width: 100%;
	height: 100%;
}

.vlg-value-card__title {
	font-size: clamp(24px, 2vw, 28px) !important;
	margin-bottom: 0.5rem;
}

.vlg-value-card p:last-child {
	font-size: 1rem;
	margin: 0;
	color: var(--wp--preset--color--secondary-text);
}

@media (max-width: 899px) {
	.vlg-value-grid {
		grid-template-columns: 1fr;
		gap: 1rem;
		margin-top: 2rem;
	}

	.vlg-value-card {
		min-height: 0;
		padding: 20px;
	}
}

/* -----------------------------------------------------------------------
 * What's included — designed inclusion grid (Tours), replacing a plain
 * bullet list. 2 columns x 3 rows desktop, 1 column mobile.
 * --------------------------------------------------------------------- */

.vlg-included-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 1.25rem;
	margin-top: 2rem;
}

/* Desktop-only: force every card in a row to the same height AND the
   same top edge. Grid's own align-items:stretch (the default) turned
   out not to be enough on its own here - confirmed live, two cards in
   the same row still differed by 24px in height because each is also
   its own flex column with variable-length text - so each card
   additionally gets an explicit height:100% to actually fill the row
   it was already stretched into.
   Separately, WordPress's default block-gap styling
   (`:where(.is-layout-flow) > * { margin-block: 1.5rem 0 }`, the exact
   mechanism documented in detail on .vlg-primary-nav/.vlg-header-cta
   further up this file) adds a silent margin-top:24px to every card
   in this grid EXCEPT the first - confirmed live: card 1 had
   margin-top:0, every other card had margin-top:24px. Even after the
   height fix above, that left the very first card of the six sitting
   24px higher than its row-mate, which is what "the first card isn't
   aligned" turned out to be, in every one of these 2/3-up card grids
   (.vlg-included-item, .vlg-good-to-know__card, .vlg-ride-card,
   .vlg-value-card - all fixed the same way, right where each already
   gets its own height:100%).
   Scoped to >=900px only; mobile already collapses to one column via
   the rule below, where equal height/top across a single column is
   meaningless. */
@media (min-width: 900px) {
	.vlg-included-grid {
		align-items: stretch;
	}

	.vlg-included-item {
		height: 100%;
		box-sizing: border-box;
		margin-top: 0;
	}
}

.vlg-included-item {
	min-height: 200px;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: 1.75rem 2rem;
	position: relative;
	border-radius: 16px !important;
	/* No side accent - the card's own inline border (a thin, neutral
	   light-border, set on the block itself) plus this shadow are what
	   define the edge now. */
	box-shadow: 0 4px 14px rgba(13, 43, 33, 0.08);
	transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.vlg-included-item:hover {
	transform: translateY(-4px);
	box-shadow: 0 12px 28px rgba(13, 43, 33, 0.14);
}

.vlg-included-item__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	flex-shrink: 0;
	color: var(--wp--preset--color--ivory-white);
	background-color: var(--wp--preset--color--gold);
	border: 2px solid var(--wp--preset--color--dark-green);
	border-radius: 50%;
	padding: 8px;
	margin-bottom: 0.85rem;
	box-shadow: 0 4px 10px rgba(214, 170, 82, 0.35);
}

.vlg-included-item__icon svg {
	width: 100%;
	height: 100%;
}

/* Deliberately larger and more distinct than the description below it
   - a title that reads the same size (or smaller) than its own body
   text looks unfinished, not premium. */
.vlg-included-item__title {
	font-size: 1.5rem !important;
	line-height: 1.2;
	color: var(--wp--preset--color--dark-green);
	margin-bottom: 0.4rem;
}

.vlg-included-item__text {
	font-size: 0.95rem;
	line-height: 1.55;
	color: var(--wp--preset--color--secondary-text);
	margin: 0;
}

@media (max-width: 899px) {
	.vlg-included-grid {
		grid-template-columns: 1fr;
		gap: 12px;
	}

	.vlg-included-item {
		min-height: 0;
		padding: 20px;
	}

	.vlg-included-item__title {
		font-size: 21px !important;
	}

	.vlg-included-item__text {
		font-size: 15px;
	}
}

/* A short centered gold rule under a bare section heading (no eyebrow
   label above it to carry the usual accent) - used by "Good to Know"
   so the section itself reads as gold-accented even though its cards
   are deliberately left plain. Reusable for any other bare H2. */
.vlg-section-heading--underline {
	position: relative;
	padding-bottom: 1rem;
}

.vlg-section-heading--underline::after {
	content: "";
	position: absolute;
	bottom: 0;
	left: 50%;
	transform: translateX(-50%);
	width: 48px;
	height: 3px;
	background-color: var(--wp--preset--color--gold);
	border-radius: 2px;
}

/* -----------------------------------------------------------------------
 * Good to know — two cards (Weather & Route / Pricing), Tours page.
 * --------------------------------------------------------------------- */

.vlg-good-to-know {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 1.5rem;
	margin-top: 1.5rem;
	align-items: stretch;
}

/* See .vlg-included-item above for why an explicit height:100% and
   margin-top:0 are both needed. Desktop-only. */
@media (min-width: 900px) {
	.vlg-good-to-know__card {
		height: 100%;
		box-sizing: border-box;
		margin-top: 0;
	}
}

.vlg-good-to-know__card {
	min-height: 200px;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: 2rem 2.25rem;
	border-radius: 16px !important;
	/* Sober on purpose: no gold side accent here - the section's own
	   gold rule (below, under the "Good to Know" heading) already
	   carries the section's accent, so the cards themselves stay
	   neutral: inline light-border + this shadow only. */
	box-shadow: 0 4px 14px rgba(13, 43, 33, 0.08);
	transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.vlg-good-to-know__card:hover {
	transform: translateY(-4px);
	box-shadow: 0 12px 28px rgba(13, 43, 33, 0.14);
}

.vlg-good-to-know__card__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	flex-shrink: 0;
	margin-bottom: 1rem;
	color: var(--wp--preset--color--ivory-white);
	background-color: var(--wp--preset--color--gold);
	border: 2px solid var(--wp--preset--color--dark-green);
	border-radius: 50%;
	padding: 9px;
	box-shadow: 0 4px 10px rgba(214, 170, 82, 0.35);
}

.vlg-good-to-know__card__icon svg {
	width: 100%;
	height: 100%;
}

.vlg-good-to-know__card h3 {
	font-size: clamp(24px, 2vw, 28px) !important;
	margin-bottom: 0.5rem;
}

.vlg-good-to-know__card p {
	color: var(--wp--preset--color--secondary-text);
	margin: 0;
}

@media (max-width: 899px) {
	.vlg-good-to-know {
		grid-template-columns: 1fr;
		gap: 12px;
	}

	.vlg-good-to-know__card {
		min-height: 0;
		padding: 20px;
	}
}

/* -----------------------------------------------------------------------
 * Two Ways to Ride — Motorcycle / Private Van comparison cards (Tours).
 * --------------------------------------------------------------------- */

.vlg-ride-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 1.5rem;
	margin-top: 2.5rem;
}

/* Same equal-height + margin-top:0 fix as .vlg-included-item -
   desktop-only. */
@media (min-width: 900px) {
	.vlg-ride-grid {
		align-items: stretch;
	}

	.vlg-ride-card {
		height: 100%;
		box-sizing: border-box;
		margin-top: 0;
	}
}

.vlg-ride-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	padding: 2.25rem 2rem;
	border-radius: 16px !important;
	/* No gold side accent - a plain, quiet border+shadow reads more
	   like a considered "option card" than a promotional one. */
	box-shadow: 0 4px 14px rgba(13, 43, 33, 0.08);
	transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.vlg-ride-card:hover {
	transform: translateY(-4px);
	box-shadow: 0 12px 28px rgba(13, 43, 33, 0.14);
}

.vlg-ride-card__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	flex-shrink: 0;
	color: var(--wp--preset--color--ivory-white);
	background-color: var(--wp--preset--color--gold);
	border: 2px solid var(--wp--preset--color--dark-green);
	border-radius: 50%;
	padding: 10px;
	margin-bottom: 1rem;
	box-shadow: 0 4px 10px rgba(214, 170, 82, 0.35);
}

.vlg-ride-card__icon svg {
	width: 100%;
	height: 100%;
}

.vlg-ride-card__title {
	font-size: clamp(22px, 2vw, 26px) !important;
	margin-bottom: 0.5rem;
}

.vlg-ride-card__text {
	font-size: 0.95rem;
	line-height: 1.55;
	color: var(--wp--preset--color--secondary-text);
	margin: 0;
}

@media (max-width: 899px) {
	.vlg-ride-grid {
		grid-template-columns: 1fr;
		gap: 12px;
		margin-top: 2rem;
	}

	.vlg-ride-card {
		padding: 28px 22px;
	}
}

/* -----------------------------------------------------------------------
 * Trust stats
 * --------------------------------------------------------------------- */

.vlg-trust-stats__row.wp-block-columns {
	display: grid !important;
	grid-template-columns: repeat(4, 1fr);
	gap: clamp(1.5rem, 4vw, 3rem);
}

.vlg-trust-stats__row > .wp-block-column {
	flex-basis: auto !important;
	width: auto !important;
	margin: 0 !important;
}

.vlg-trust-stat {
	text-align: center;
}

.vlg-trust-stat h3 {
	font-size: clamp(2rem, 1.6rem + 2vw, 2.75rem);
	margin-bottom: 0.25rem;
	/* Reverted: oldstyle-nums on Cormorant Garamond renders "1" and "0"
	   almost identically to capital "I" and "O" at this size/weight in
	   the browsers tested live - "100%"/"10+" became unreadable as
	   "IOO%"/"IO+". Confirmed on the real site; not worth the legibility
	   cost on numbers this important. */
}

@media (max-width: 899px) {
	.vlg-trust-stats {
		--wp--style--block-gap: 0.75rem;
	}

	.vlg-trust-stats__row.wp-block-columns {
		grid-template-columns: repeat(2, 1fr);
		margin-top: 0.5rem;
	}

	.vlg-trust-stat h3 {
		font-size: clamp(28px, 6vw, 31px) !important;
	}

	.vlg-trust-stat p {
		font-size: clamp(14px, 3vw, 15px) !important;
		line-height: 1.4;
	}
}

@media (max-width: 400px) {
	.vlg-trust-stats__row.wp-block-columns {
		grid-template-columns: 1fr;
	}
}

/* -----------------------------------------------------------------------
 * Tour cards — equal width & height, real images, rounded corners,
 * always centered inside .vlg-container (never left-aligned).
 * --------------------------------------------------------------------- */

.vlg-tour-grid {
	display: grid !important;
	grid-template-columns: repeat(3, 1fr);
	gap: clamp(1.5rem, 3vw, 32px);
	justify-content: center;
	align-items: stretch;
}

.vlg-tour-grid.wp-block-columns,
.vlg-tour-grid.wp-block-group {
	flex-wrap: wrap;
}

.vlg-tour-grid > .wp-block-column {
	flex-basis: auto !important;
	width: auto !important;
	margin: 0 !important;
}

.vlg-tour-card {
	height: 100%;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	/* The card's own padding — kept in the CSS class (not the block's
	   inline style) so it can be a single responsive value shared with
	   .vlg-tour-card__image's bleed margin below. Desktop 28px, mobile
	   20px (spec: "cards more compact than currently"). */
	padding: 28px;
	transition: transform 0.2s ease, box-shadow 0.2s ease;
	/* Card-background sits very close to the page's main-cream, so the
	   original faint shadow barely read against it - deepened here for
	   real contrast. No gold side accent (removed in favour of spreading
	   gold more sparingly across the site: price + button stay gold,
	   the card edge itself stays neutral - inline light-border + this
	   shadow define it instead). */
	box-shadow: 0 4px 16px rgba(13, 43, 33, 0.1);
}

.vlg-tour-card:hover {
	transform: translateY(-4px);
	box-shadow: 0 12px 28px rgba(13, 43, 33, 0.14);
}

/* Home's "Crafted for curious minds" cards read slightly more editorial
   than Tours' own four cards - no border at all (a plain photo-led
   card resting purely on its shadow), where Tours keeps a thin
   neutral border for a touch more definition on its "shop" page. */
.vlg-tour-grid--featured .vlg-tour-card {
	border-width: 0 !important;
	box-shadow: 0 3px 14px rgba(13, 43, 33, 0.07);
}

.vlg-tour-grid--featured .vlg-tour-card:hover {
	box-shadow: 0 10px 24px rgba(13, 43, 33, 0.12);
}

.vlg-tour-card__image {
	margin: -28px -28px 1.1rem;
	aspect-ratio: 4 / 3;
	overflow: hidden;
}

.vlg-tour-card .wp-block-button.has-custom-width {
	max-width: 260px;
}

@media (max-width: 899px) {
	.vlg-tour-card {
		padding: 20px;
		border-radius: 16px !important;
	}

	.vlg-tour-card__image {
		margin: -20px -20px 1rem;
	}

	.vlg-tour-card h3 {
		font-size: clamp(24px, 6vw, 27px) !important;
		line-height: 1.12;
	}

	.vlg-tour-card__description {
		font-size: 15.5px;
		line-height: 1.55;
	}

	.vlg-tour-card__price {
		font-size: 19px;
	}
}

.vlg-tour-card__image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: 0;
	transition: transform 0.4s ease;
}

/* The Temple & Local Life / Cultural Temples photo is a tall portrait
   shot (statue + towers) forced into this landscape 4:3 box - cover
   was cropping the top or base off the statue. Show the whole photo
   letterboxed on a soft fill instead, so nothing important is cut. */
.vlg-tour-card__image--contain img {
	object-fit: contain;
	background-color: var(--wp--preset--color--light-sage);
}

/* Home only (.vlg-tour-grid--featured) - the Tours page keeps its own
   letterboxed --contain treatment above, untouched. Desktop here is
   also left exactly as it already was (same letterboxed treatment);
   only the mobile crop below changes, per this pass's "preserve
   desktop" rule - the pale side-bar complaint was mobile-specific. */
.vlg-tour-card__image--temple-crop img {
	object-fit: contain;
	background-color: var(--wp--preset--color--light-sage);
}

/* Mobile only: fill the frame with no side bars, anchored so the
   statue stays fully visible and the tourist group standing at the
   base of the photo is cropped out. */
@media (max-width: 899px) {
	.vlg-tour-card__image--temple-crop img {
		object-fit: cover;
		background-color: transparent;
		object-position: 50% 5%;
	}
}

/* Tours page's own "Cultural Temples & Local Life" card: unlike the
   Home card above, this one should show the cropped, statue-focused
   framing at every width, not just mobile - requested for both desktop
   and mobile here. Same object-position, since the card's image box is
   the same 4:3 ratio at any size. */
.vlg-tour-card__image--temple-crop-full img {
	object-fit: cover;
	object-position: 50% 5%;
}

/* Premium detail: a very subtle image zoom on desktop card hover. */
@media (hover: hover) and (min-width: 900px) {
	.vlg-tour-card:hover .vlg-tour-card__image img {
		transform: scale(1.04);
	}
}

@media (prefers-reduced-motion: reduce) {
	.vlg-tour-card__image img {
		transition: none;
	}
}

.vlg-tour-card h3 {
	margin-bottom: 0.5rem;
}

.vlg-tour-card__description {
	flex-grow: 1;
	color: var(--wp--preset--color--secondary-text);
}

.vlg-tour-card__meta {
	align-items: baseline;
	flex-wrap: wrap;
	gap: 0.5rem;
	/* Pins the meta/price row (and whatever follows it - the final-price
	   note, the Check Availability button) to the bottom of the card
	   regardless of description length, so all cards in a row line up
	   on desktop (.vlg-tour-grid stretches every card to the row's
	   tallest height). */
	margin-top: auto;
	padding-top: 1rem;
	border-top: 1px solid var(--wp--preset--color--light-border);
}

.vlg-tour-card__meta-label {
	display: block;
	font-size: 0.7rem;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--wp--preset--color--secondary-text);
	margin-bottom: 0.15rem;
}

.vlg-tour-card__price {
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.3rem;
	font-weight: 600;
	/* oldstyle-nums removed: confirmed live that Cormorant Garamond
	   renders "0"/"1" as near-identical to "O"/"I" - unacceptable on a
	   real price like "850,000 VND". */
}

@media (max-width: 1023px) {
	.vlg-tour-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

/* Tours page: exactly four cards, 2x2 on desktop/tablet, each card
   filling its full grid cell (never a narrow floating card). */
.vlg-tour-grid--four {
	grid-template-columns: repeat(2, 1fr);
}

.vlg-tour-grid--four .vlg-tour-card {
	width: 100%;
}

/* Mobile (<900px, the project's mobile breakpoint): one card per row
   everywhere, full container width, never a narrow floating card. */
@media (max-width: 899px) {
	.vlg-tour-grid,
	.vlg-tour-grid--four {
		grid-template-columns: 1fr;
	}
}

/* -----------------------------------------------------------------------
 * Testimonial cards / FAQ items
 * --------------------------------------------------------------------- */

/* Equal-height card grid: every note sits in a card of the same size
   (align-items:stretch), with the attribution pinned to the bottom of
   each card via margin-top:auto regardless of how long the transcript
   is - a consistent card silhouette reads far more premium than a
   masonry stagger. 3 columns desktop, 2 tablet, 1 mobile. */
.vlg-guest-book-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: clamp(1.5rem, 3vw, 2rem);
	align-items: stretch;
}

/* Desktop-only (matches this grid's own 3-column breakpoint below,
   >=1024px - tablet's 2-column and mobile's 1-column layouts are
   untouched):
   1) explicit height:100% so every card in a row is genuinely equal
      height (see .vlg-included-item above for why align-items:stretch
      alone isn't enough here).
   2) margin-top:0 - confirmed live, WordPress's own default block-gap
      styling (see the .vlg-primary-nav/.vlg-header-cta comment above
      for the exact mechanism) adds a 24px margin-top to every card
      EXCEPT the first, since it only targets non-first children. That
      alone explained two symptoms at once: the first card sitting 24px
      higher than its own row-mates, and the last (lone, centered) card
      overflowing 24px past where the grid container itself ended,
      overlapping the "Every entry here is handwritten..." paragraph
      right below it.
   3) with an odd card count, the last one lands alone in column 1 of
      the final row - :last-child combined with :nth-child(3n+1) is
      true whenever that lone card would start a *new* row (column 1),
      which only happens when it is alone there; centering it into the
      middle column then reads as intentional instead of stuck to the
      left. This is entirely count-agnostic: it keeps working correctly
      however many testimonial cards this grid ever holds, with nothing
      to update if one is added or removed. */
@media (min-width: 1024px) {
	.vlg-testimonial-card {
		height: 100%;
		box-sizing: border-box;
		margin-top: 0;
	}

	.vlg-guest-book-grid > .vlg-testimonial-card:last-child:nth-child(3n + 1) {
		grid-column: 2 / 3;
	}
}

@media (max-width: 1023px) {
	.vlg-guest-book-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 767px) {
	.vlg-guest-book-grid {
		grid-template-columns: 1fr;
	}
}

.vlg-testimonial-card {
	display: flex;
	flex-direction: column;
	padding: 1.5rem;
	box-shadow: 0 3px 14px rgba(13, 43, 33, 0.08);
	border-radius: 12px;
}

.vlg-testimonial-card .wp-block-image {
	overflow: hidden;
	border-radius: 8px;
	margin: 0 0 1.1rem;
}

.vlg-testimonial-card .wp-block-image img {
	transition: transform 0.4s ease;
}

/* Premium detail: a very subtle image zoom on desktop hover. */
@media (hover: hover) and (min-width: 900px) {
	.vlg-testimonial-card:hover .wp-block-image img {
		transform: scale(1.03);
	}
}

@media (prefers-reduced-motion: reduce) {
	.vlg-testimonial-card .wp-block-image img {
		transition: none;
	}
}

.vlg-testimonial-card__quote {
	font-style: italic;
	color: var(--wp--preset--color--main-dark-text);
}

/* Pins the attribution to the bottom of the card regardless of quote
   length, so every card - short note or long one - lines up the same
   way at both top (image) and bottom (name/country/year). */
.vlg-testimonial-card__meta {
	margin-top: auto;
	padding-top: 0.75rem;
}

@media (max-width: 899px) {
	.vlg-testimonial-card__quote {
		font-size: 16px !important;
		line-height: 1.6;
	}

	.vlg-testimonial-card__meta {
		font-size: 14px !important;
	}
}

.vlg-faq-item {
	margin-bottom: 1rem;
	background-color: var(--wp--preset--color--card-background);
	border: 1px solid var(--wp--preset--color--light-border);
	border-radius: 16px;
	/* Very subtle - no gold accent on the card itself, just enough
	   shadow to lift it off the light-sage section background. */
	box-shadow: 0 2px 10px rgba(13, 43, 33, 0.05);
	overflow: hidden;
}

.vlg-faq-item__question {
	margin: 0;
}

/* The whole question row is a real <button> - clickable everywhere,
   not just on the text, and free keyboard/focus support. */
.vlg-faq-item__toggle {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	width: 100%;
	padding: 1.5rem 1.75rem;
	background: none;
	border: none;
	margin: 0;
	cursor: pointer;
	text-align: left;
	font-family: var(--wp--preset--font-family--heading);
	font-size: clamp(20px, 1.5vw, 22px);
	font-weight: 600;
	color: var(--wp--preset--color--dark-green);
}

.vlg-faq-item__toggle:focus-visible {
	outline: 2px solid var(--wp--preset--color--gold-hover);
	outline-offset: -2px;
}

/* A plus that turns into a minus on open - two bars, the vertical one
   scales away instead of rotating, so it never looks like a spinning
   cross mid-animation. */
.vlg-faq-item__icon {
	position: relative;
	flex-shrink: 0;
	width: 20px;
	height: 20px;
}

.vlg-faq-item__icon::before,
.vlg-faq-item__icon::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	background-color: var(--wp--preset--color--gold);
	transition: transform 0.25s ease;
}

.vlg-faq-item__icon::before {
	width: 14px;
	height: 2px;
	transform: translate(-50%, -50%);
}

.vlg-faq-item__icon::after {
	width: 2px;
	height: 14px;
	transform: translate(-50%, -50%);
}

.vlg-faq-item.is-open .vlg-faq-item__icon::after {
	transform: translate(-50%, -50%) scaleY(0);
}

/* The grid-template-rows 0fr/1fr trick: animates a true "auto height"
   open/close with a plain CSS transition, no JS height measuring and
   no abrupt jump shut. */
.vlg-faq-item__panel {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows 0.3s ease;
}

.vlg-faq-item.is-open .vlg-faq-item__panel {
	grid-template-rows: 1fr;
}

.vlg-faq-item__panel-inner {
	overflow: hidden;
	min-height: 0;
}

.vlg-faq-item__answer {
	font-size: 16px;
	color: var(--wp--preset--color--secondary-text);
	margin: 0;
	padding: 0 1.75rem 1.5rem;
}

@media (prefers-reduced-motion: reduce) {
	.vlg-faq-item__panel {
		transition: none;
	}

	.vlg-faq-item__icon::before,
	.vlg-faq-item__icon::after {
		transition: none;
	}
}

@media (max-width: 899px) {
	.vlg-faq-item__toggle {
		padding: 1.25rem;
		font-size: clamp(18px, 4vw, 20px);
	}

	.vlg-faq-item__answer {
		padding: 0 1.25rem 1.25rem;
	}
}

/* Contact hero — a compact dark-green banner, never near-full-screen. */
@media (max-width: 899px) {
	.vlg-contact-hero {
		padding-top: 56px !important;
		padding-bottom: 56px !important;
	}
}

/* -----------------------------------------------------------------------
 * Gallery grid — native Gallery/Image block handles lazy loading and the
 * lightbox (theme.json settings.lightbox); this tunes the grid itself.
 * --------------------------------------------------------------------- */

.vlg-gallery-grid.wp-block-gallery {
	--wp--style--unstable-gallery-gap: 1rem;
	gap: 1rem;
	justify-content: center;
}

.vlg-gallery-grid .wp-block-image {
	aspect-ratio: 4 / 3;
	overflow: hidden;
	border-radius: 14px;
	margin: 0;
}

.vlg-gallery-grid .wp-block-image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: 14px;
	transition: transform 0.4s ease;
}

/* This one photo (the tall standing Buddha statue) is a portrait shot -
   the shared 4:3 landscape crop above was cutting off its head or base.
   A taller cell matching the photo's own ratio shows it in full instead
   of cropping it to fit the grid. */
.vlg-gallery-grid .wp-block-image.vlg-gallery-tall {
	aspect-ratio: 4 / 5;
}

/* Premium detail: a very subtle image zoom on desktop hover. */
@media (hover: hover) and (min-width: 900px) {
	.vlg-gallery-grid .wp-block-image:hover img {
		transform: scale(1.04);
	}
}

@media (prefers-reduced-motion: reduce) {
	.vlg-gallery-grid .wp-block-image img {
		transition: none;
	}
}

@media (max-width: 781px) {
	.vlg-gallery-grid.wp-block-gallery.columns-3,
	.vlg-gallery-grid.wp-block-gallery.columns-4 {
		grid-template-columns: repeat(2, 1fr) !important;
	}
}

@media (max-width: 899px) {
	.vlg-gallery-grid.wp-block-gallery {
		--wp--style--unstable-gallery-gap: 13px;
		gap: 13px;
	}

	.vlg-gallery-preview > .vlg-text-container {
		max-width: 560px;
	}
}

@media (max-width: 480px) {
	.vlg-gallery-grid.wp-block-gallery {
		grid-template-columns: 1fr !important;
	}
}

.vlg-gallery-category h2 {
	margin-bottom: 0.35rem;
}

@media (max-width: 899px) {
	.vlg-gallery-category h2 {
		font-size: clamp(30px, 7vw, 34px) !important;
	}
}

/* -----------------------------------------------------------------------
 * Pull quotes (Home gallery preview)
 * --------------------------------------------------------------------- */

.vlg-pull-quote {
	font-style: italic;
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--large);
	text-align: center;
}

.vlg-pull-quote__meta {
	display: block;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-style: normal;
	color: var(--wp--preset--color--secondary-text);
	margin-top: 0.5rem;
}

/* Mobile: hardcoded px, not the "large"/"small" preset variables above.
   Global Styles saved in wp-admin currently resolve --wp--preset--font-
   size--large to 36px (live-verified), far above theme.json's own
   clamp() - these quotes were rendering nearly twice the intended size
   on phones as a result. Fixed values sidestep that mismatch entirely. */
@media (max-width: 899px) {
	.vlg-pull-quotes {
		gap: 32px;
	}

	.vlg-pull-quote {
		font-size: 26px !important;
		line-height: 1.34 !important;
	}

	.vlg-pull-quote__meta {
		font-size: 14px !important;
	}
}

/* -----------------------------------------------------------------------
 * Single quote blocks (About Vinh, Gallery closing quote)
 * --------------------------------------------------------------------- */

.vlg-single-quote {
	text-align: center;
	max-width: 760px;
	margin-inline: auto;
	padding: 2.5rem 2rem;
	box-shadow: 0 4px 16px rgba(13, 43, 33, 0.1);
}

/* A large decorative quotation mark instead of a line or side accent -
   a typographic flourish (Cormorant Garamond's own quote glyph, gold)
   that reads as more editorial and gives this card real variety next
   to the site's other icon-circle / gold-line card accents. */
.vlg-single-quote::before {
	content: "\201C";
	display: block;
	font-family: var(--wp--preset--font-family--heading);
	font-size: 3.5rem;
	line-height: 0.6;
	color: var(--wp--preset--color--gold);
	margin-bottom: 0.5rem;
}

.vlg-single-quote__text {
	font-style: italic;
}

@media (max-width: 899px) {
	.vlg-single-quote {
		padding: 2rem 1.25rem;
	}

	.vlg-single-quote__text {
		font-size: clamp(22px, 5.5vw, 25px) !important;
	}
}

/* Home Guest Book preview: same quote-size treatment as .vlg-single-
   quote above but this block isn't wrapped in that class (it sits
   directly in .vlg-guest-book-preview), and its own heading/attribution/
   body/button need the same mobile tightening as every other Home
   section in this pass. */
@media (max-width: 899px) {
	.vlg-guest-book-preview {
		--wp--style--block-gap: 1rem;
	}

	.vlg-guest-book-preview .has-secondary-text-color {
		font-size: 14px;
	}
}

/* -----------------------------------------------------------------------
 * Booking checklist (Contact)
 * --------------------------------------------------------------------- */

.vlg-booking-checklist {
	position: relative;
	overflow: hidden;
	padding: 3rem 2.75rem;
	box-shadow: 0 10px 34px rgba(13, 43, 33, 0.1);
	border: 1px solid rgba(214, 170, 82, 0.55);
}

/* A slim gold accent bar along the top - clipped to the card's own
   rounded corners (overflow:hidden above) - marks this as the
   featured, "start here" card rather than a plain bordered box. */
.vlg-booking-checklist::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 4px;
	background-color: var(--wp--preset--color--gold);
}

.vlg-booking-checklist__heading {
	font-size: clamp(28px, 2vw, 32px) !important;
	margin-bottom: 1.5rem;
}

.vlg-booking-checklist__list {
	list-style: none;
	margin: 0 0 1.75rem;
	padding: 0;
	max-width: 360px;
	margin-inline: auto;
}

.vlg-booking-checklist__list li {
	position: relative;
	padding-left: 1.8rem;
	font-size: 17px;
	text-align: left;
	margin-bottom: 0.85rem;
	/* The card's background is dark green (see the template), so the
	   list text needs to be light instead of the site's default dark
	   body text. */
	color: var(--wp--preset--color--light-sage);
}

.vlg-booking-checklist__list li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.5em;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background-color: var(--wp--preset--color--gold);
}

.vlg-contact-buttons {
	margin-top: 1.5rem;
}

.vlg-contact-buttons .wp-block-button {
	max-width: 280px;
}

/* Desktop-only: the list above stays left-aligned (its own dots/text
   need a stable left edge to line up - see the mobile block below for
   why that logic exists), but the two buttons read better as one
   centered, evenly-matched pair rather than pinned to the list's left
   edge. Equal width (not just a shared max-width, which still let
   "Chat on WhatsApp" render wider than "Chat on Zalo") is what makes
   them read as a deliberate pair instead of two mismatched buttons. */
@media (min-width: 900px) {
	.vlg-contact-buttons {
		justify-content: center;
		margin-top: 2rem;
	}

	.vlg-contact-buttons .wp-block-button {
		flex: 0 1 200px;
		max-width: 200px;
	}

	.vlg-contact-buttons .wp-block-button__link {
		justify-content: center;
	}
}

@media (max-width: 899px) {
	.vlg-booking-checklist {
		width: calc(100% - 40px);
		margin-inline: auto;
		padding: 2.25rem 1.5rem;
	}

	.vlg-booking-checklist__heading {
		font-size: clamp(30px, 8vw, 34px) !important;
	}

	/* Center the checklist as a whole block, on mobile only, while
	   keeping every row's dot and text lined up with each other.
	   Centering each <li> independently (an earlier attempt) let the
	   dot's position drift row to row, since rows have different text
	   lengths and each was centered as its own variable-width unit -
	   dots ended up staggered instead of forming a clean line. Fix:
	   let the list shrink to fit its widest row (width:fit-content)
	   and center THAT as one block; align-items:stretch then makes
	   every row match that same width, so a shared left-aligned
	   dot+text layout inside each row lines up identically across all
	   of them, and the block still reads as centered in the card. */
	.vlg-booking-checklist__list {
		display: flex;
		flex-direction: column;
		align-items: stretch;
		width: fit-content;
		margin-inline: auto;
	}

	.vlg-booking-checklist__list li {
		display: flex;
		align-items: center;
		gap: 10px;
		padding-left: 0;
		text-align: left;
		font-size: 17px;
	}

	.vlg-booking-checklist__list li::before {
		position: static;
		flex-shrink: 0;
	}

	.vlg-contact-buttons {
		flex-direction: column;
		align-items: stretch;
	}

	.vlg-contact-buttons .wp-block-button {
		max-width: none;
	}

	.vlg-contact-buttons .wp-block-button__link {
		text-align: center;
	}

	/* Same primary/secondary system used elsewhere: secondary (Zalo) is
	   transparent with a gold border. This card's background is dark
	   green (see the template), so light text - not the dark text an
	   earlier version of this card needed when it had a cream
	   background. */
	.vlg-contact-buttons .is-style-vlg-secondary .wp-block-button__link {
		background-color: transparent;
		border: 2px solid var(--wp--preset--color--gold);
		color: var(--wp--preset--color--ivory-white);
	}

	.vlg-testimonial-card .wp-block-image img {
		width: 100%;
	}
}

/* -----------------------------------------------------------------------
 * Final CTA — ONE single component: the page-specific heading and the
 * shared paragraph+buttons (patterns/booking-cta.php) are both direct
 * children of this one .vlg-booking-cta group, so there is exactly one
 * dark-green box and one padding box - never two separate rectangles
 * with a gap between them.
 * --------------------------------------------------------------------- */

.vlg-booking-cta {
	position: relative;
	overflow: hidden;
	background-color: var(--wp--preset--color--dark-green);
	border: 1px solid rgba(214, 170, 82, 0.55);
	border-radius: 20px;
	text-align: center;
	max-width: 1080px;
	margin-inline: auto;
	padding: 52px 48px;
}

.vlg-booking-cta > * {
	position: relative;
	z-index: 1;
}

.vlg-booking-cta__heading {
	color: var(--wp--preset--color--ivory-white);
	margin: 0 0 1rem;
}

.vlg-booking-cta__text {
	max-width: 700px;
	margin: 0 auto 1.75rem;
}

.vlg-booking-cta__buttons {
	margin: 0;
}

@media (max-width: 899px) {
	.vlg-booking-cta {
		max-width: none;
		width: 100%;
		padding: 36px 20px;
	}

	.vlg-booking-cta__heading {
		font-size: clamp(32px, 8vw, 36px) !important;
		line-height: 1.1 !important;
	}

	.vlg-booking-cta__text {
		font-size: 16px !important;
		line-height: 1.55;
		margin-bottom: 1.25rem;
	}

	/* "Chat on WhatsApp" and "Chat on Zalo" aren't the same length, so
	   without an explicit width each button sized to its own text and
	   they came out visibly different widths. align-items:stretch (an
	   earlier attempt) fixed the width match but, once the shared
	   max-width:280px rule capped that stretched size, the leftover
	   space collapsed to one side instead of splitting evenly - the
	   pair rendered flush against the card's left edge instead of
	   centered (confirmed live: 0px gap on the left, ~23px on the
	   right). align-items:center + an explicit width:100% on the
	   button (which max-width:280px still caps) is what actually
	   centers a capped-width flex item. */
	.vlg-booking-cta__buttons {
		flex-direction: column;
		align-items: center;
		gap: 14px;
	}

	.vlg-booking-cta__buttons .wp-block-button {
		width: 100%;
	}

	/* Same primary/secondary system as the Home hero: secondary (Zalo)
	   goes transparent with a gold border and light text against this
	   card's dark green background. */
	.vlg-booking-cta__buttons .is-style-vlg-secondary .wp-block-button__link {
		background-color: transparent;
		border: 2px solid var(--wp--preset--color--gold);
		color: var(--wp--preset--color--ivory-white);
	}
}

/* -----------------------------------------------------------------------
 * Footer — full 1240px container, balanced grid
 * --------------------------------------------------------------------- */

.vlg-site-footer {
	padding-top: clamp(48px, 5vw, 56px);
	padding-bottom: 28px;
}

/* Desktop: three real columns — brand | navigation | reach out —
   instead of nesting navigation+contact together inside one column. */
.vlg-footer-top {
	display: grid;
	grid-template-columns: minmax(220px, 300px) 1fr minmax(200px, 260px);
	gap: clamp(2rem, 5vw, 3.5rem);
	align-items: start;
}

.vlg-footer-brand__logo img {
	width: 170px;
	height: auto;
	margin-bottom: 1rem;
}

.vlg-footer-brand__title {
	margin-bottom: 0.5rem;
}

.vlg-footer-brand__tagline {
	color: var(--wp--preset--color--light-sage);
	opacity: 0.85;
}

.vlg-footer-nav-col > .wp-block-heading {
	margin-bottom: 0.75rem;
}

.vlg-footer-nav {
	margin-top: 0.5rem;
}

.vlg-footer-nav a {
	color: var(--wp--preset--color--light-sage);
	font-size: 0.95rem;
}

.vlg-footer-nav a:hover {
	color: var(--wp--preset--color--gold);
}

.vlg-footer-contact__title {
	color: var(--wp--preset--color--ivory-white);
	margin-bottom: 0.75rem;
}

.vlg-footer-contact a {
	color: var(--wp--preset--color--ivory-white);
	font-weight: 600;
}

.vlg-footer-separator {
	margin: 2rem 0 1.25rem;
	opacity: 0.35;
}

.vlg-footer-bottom {
	padding-bottom: 0;
	gap: 0.75rem;
}

.vlg-footer-copyright,
.vlg-footer-tagline {
	color: var(--wp--preset--color--light-sage);
	opacity: 0.8;
	margin: 0;
}

.vlg-footer-legal-sep {
	opacity: 0.6;
}

.vlg-footer-legal-link {
	color: var(--wp--preset--color--light-sage);
	text-decoration: underline;
	text-decoration-color: rgba(214, 170, 82, 0.5);
}

.vlg-footer-legal-link:hover,
.vlg-footer-legal-link:focus-visible {
	color: var(--wp--preset--color--gold);
}

/* -----------------------------------------------------------------------
 * Footer — desktop-only premium refinement. The mobile block below (its
 * own @media max-width:899px, already comprehensive) is untouched by
 * anything here; every rule in this block only ever applies >=900px.
 * --------------------------------------------------------------------- */
@media (min-width: 900px) {
	/* A hairline gold rule along the very top of the footer - the one
	   thing separating it from the section above was its background
	   color change alone; this gives it a deliberate, considered edge
	   instead of just "the green part starts here". */
	/* Latest spec asks for a more compact 48-56px/36-44px pair than the
	   previous round's 60px/40px - a bit less "air" at the very top,
	   closer to the original 52px this footer shipped with several
	   rounds ago, now paired with a subtle gradient (below) instead of
	   a flat fill so the reduced padding still reads considered rather
	   than cramped. */
	.vlg-site-footer {
		border-top: 1px solid rgba(214, 170, 82, 0.35);
		padding-top: 52px;
		padding-bottom: 22px;
		/* A quiet diagonal deepening (secondary-green into dark-green)
		   instead of one flat fill - the kind of subtle depth a flat
		   "WordPress default footer" never has. Sits on top of the
		   existing has-dark-green-background-color utility class as a
		   background-image layer, so it doesn't fight that class's own
		   background-color for specificity. */
		background-image: linear-gradient(160deg, rgba(23, 60, 48, 0.55) 0%, rgba(13, 43, 33, 1) 55%);
	}

	/* A tighter, intentional hairline instead of the bare 2rem/1.25rem
	   default - 40px stays within the requested 36-44px range. */
	.vlg-footer-separator {
		margin: 40px 0 14px;
	}

	/* Back to the 1.4fr/0.8fr/1fr ratio and a 70-100px gap per the
	   latest spec (previous round had pushed to 1.35fr/0.9fr/1fr and
	   80-110px) - still fr-based so it fills the real .vlg-container
	   width (1240px at 1440px+) with zero dead space on either side,
	   confirmed live at 1024/1280/1440/1920px. */
	.vlg-footer-top {
		grid-template-columns: 1.4fr 0.8fr 1fr;
		gap: clamp(70px, 6vw, 100px);
		align-items: start;
	}

	/* A subtle premium touch the previous rounds didn't have: a
	   hairline gold divider centered in the gutter between Brand/
	   Navigation and Navigation/Reach Out, so the three columns read as
	   deliberately organized sections instead of just floating text in
	   a large green field. Reuses the exact same gap formula for its
	   offset so it stays centered in the gutter at every viewport width
	   instead of drifting as the fluid gap changes. Low opacity (0.2) -
	   present on close inspection, invisible as a distraction. */
	.vlg-footer-nav-col,
	.vlg-footer-contact {
		position: relative;
	}

	.vlg-footer-nav-col::before,
	.vlg-footer-contact::before {
		content: "";
		position: absolute;
		top: 2px;
		bottom: 2px;
		left: calc(clamp(70px, 6vw, 100px) / -2);
		width: 1px;
		background: rgba(214, 170, 82, 0.2);
	}

	/* .vlg-footer-top is itself a WordPress group block, so its three
	   column children inherit the exact same default block-gap margin
	   documented in detail on .vlg-primary-nav/.vlg-header-cta earlier
	   in this file: margin-top:24px on every child except the first -
	   confirmed live again here. .vlg-footer-bottom (a sibling of
	   .vlg-footer-top/.vlg-footer-separator inside the same .vlg-container)
	   gets the identical treatment, confirmed live with its own
	   unwanted 24px margin-top. */
	.vlg-footer-top > *,
	.vlg-footer-bottom {
		margin-top: 0;
	}

	/* No longer artificially capped - Brand is deliberately the widest
	   column (see grid-template-columns above), matching its role as
	   the site's actual identity block. */
	.vlg-footer-brand {
		max-width: none;
	}

	/* Logo crop-zoom, same technique as the mobile header logo further
	   up this file: the source PNG is a 300x300 canvas, but pixel-
	   sampled live, the actual visible mark (icon + wordmark) only
	   occupies a ~260x152px band inside it (x:22-282, y:61-213) - most
	   of the canvas is transparent padding. Sizing the <img> by width/
	   height alone scales that padding right along with it, so the mark
	   itself renders far smaller than the declared size. Latest spec
	   asks for 110-130px visible (down from the previous round's
	   140-170px) - targeting ~120px: rendering the image at 139px
	   (scale 0.463) then cropping a window sized to the scaled mark
	   (~120x70px) plus a small margin delivers a ~120px-wide VISIBLE
	   logo - still the exact same file, exact ratio, no upscale (139px
	   is a fraction of the source's real 300px resolution), no CSS blur
	   filter of any kind. Math verified against the same pixel-sampled
	   bounding box: at this scale/margin the mark sits fully inside the
	   128x78 window with a margin on all four sides, nothing clipped. */
	.vlg-footer-brand__logo {
		display: block;
		width: 128px;
		height: 78px;
		overflow: hidden;
		margin: 0;
	}

	.vlg-footer-brand__logo img {
		width: 139px;
		height: 139px;
		max-width: none;
		margin: -24px 0 0 -6px;
	}

	/* 1.1rem (~17.6px), within the latest "16-18px" spec, with an
	   explicit 700 weight (theme.json headings default to 600) so the
	   brand name is clearly legible and not minuscule. */
	.vlg-footer-brand__title {
		font-size: 1.1rem;
		font-weight: 700;
		margin-top: 0.7rem;
		margin-bottom: 0.4rem;
	}

	/* 0.92rem (~14.7px) / max-width 300px, matching the latest "14-15px
	   / ~300px" spec - a comfortable paragraph, not stretched edge to
	   edge, not cramped either. */
	.vlg-footer-brand__tagline {
		max-width: 300px;
		font-size: 0.92rem;
		line-height: 1.6;
		margin-top: 0.3rem;
	}

	/* "NAVIGATION" / "REACH OUT" as quiet section labels (same idea as
	   .vlg-eyebrow used across the rest of the site) rather than
	   full-weight headings - lets the links/numbers below carry the
	   visual weight instead of competing with their own column title.
	   "NAVIGATION" needs color !important specifically: its block in
	   footer.html carries an explicit textColor:"ivory-white", which
	   WordPress's generated global-styles stylesheet compiles to
	   ".has-ivory-white-color{color:...!important}" - confirmed live,
	   that class beat this rule's color regardless of specificity until
	   !important was added here too. "REACH OUT" never had that class
	   in its own pattern, so it was never affected. */
	.vlg-footer-nav-col > .wp-block-heading,
	.vlg-footer-contact__title {
		font-size: 0.875rem !important;
		font-weight: 700;
		letter-spacing: 0.12em;
		text-transform: uppercase;
		color: var(--wp--preset--color--gold) !important;
		opacity: 0.9;
		margin-bottom: 0.75rem !important;
	}

	/* Same has-ivory-white-color !important collision as above. */
	.vlg-footer-brand__title {
		color: var(--wp--preset--color--gold) !important;
	}

	/* A slightly more generous row-gap (was 0.5rem) so the seven links
	   read as a comfortable, deliberately spaced list per "line-height
	   confortable... gap régulier", not a cramped stack. */
	.vlg-footer-nav .wp-block-navigation__container {
		row-gap: 0.65rem;
	}

	/* A quiet, premium hover - a thin gold underline growing in from the
	   left - instead of only a color change, so the column reads as a
	   deliberately designed link list rather than a bare block of text.
	   0.93rem (~14.9px) lands inside the latest "14-15px" spec. */
	.vlg-footer-nav a {
		position: relative;
		display: inline-block;
		font-size: 0.93rem;
	}

	.vlg-footer-nav a::after {
		content: "";
		position: absolute;
		left: 0;
		bottom: -3px;
		width: 0;
		height: 1px;
		background-color: var(--wp--preset--color--gold);
		transition: width 0.2s ease;
	}

	.vlg-footer-nav a:hover::after,
	.vlg-footer-nav a[aria-current="page"]::after {
		width: 100%;
	}

	@media (prefers-reduced-motion: reduce) {
		.vlg-footer-nav a::after {
			transition: none;
		}
	}

	/* font-size set on the whole paragraph, not just the link inside it
	   - confirmed live the "WhatsApp:"/"Zalo:" label text was inheriting
	   a much larger (20px) default paragraph size unrelated to the
	   .vlg-footer-contact a rule below, which only ever styled the
	   number itself, leaving a visibly mismatched label/number pair.
	   white-space:nowrap is the hard guarantee the phone numbers never
	   wrap - the column width alone (from the 1fr track above) was
	   already generous enough with room to spare, confirmed live down
	   to 1024px, but nowrap makes that a rule rather than a coincidence. */
	/* 0.94rem (~15px), within the latest "14-15px" spec, with a 500
	   weight so "Reach Out" still reads with real presence rather than
	   plain body text. white-space:nowrap remains the hard guarantee
	   the numbers never wrap to a second line; re-verified via
	   Range.getBoundingClientRect() against the rendered text width
	   that neither line overflows its column at 1024px, the narrowest
	   tested desktop width. */
	.vlg-footer-contact__line {
		font-size: 0.94rem;
		font-weight: 500;
		margin-top: 0.5rem;
		margin-bottom: 0.85rem;
		white-space: nowrap;
	}

	.vlg-footer-contact a {
		font-size: 0.94rem;
		font-weight: 500;
		letter-spacing: 0.01em;
	}

	/* No longer artificially narrowed - shares the exact same
	   .vlg-container the three-column grid above it sits in, so it
	   reads as the footer's closing line rather than a separate,
	   disconnected bar. */
	.vlg-footer-bottom {
		max-width: none;
		margin-inline: 0;
	}

	.vlg-footer-copyright,
	.vlg-footer-tagline {
		font-size: 0.8rem;
	}
}

/* Mobile: shorter footer overall — tighter padding, centered stack,
   navigation as a compact 2-column grid instead of one long list. */
@media (max-width: 899px) {
	.vlg-site-footer {
		padding-top: clamp(36px, 7vw, 48px);
		padding-bottom: 24px;
		/* Halves every WordPress-generated block-gap margin inside the
		   footer (between the brand/nav/contact columns, and between
		   each column's own heading and its content) - the single
		   biggest lever on the footer's total mobile height, since it
		   was stacking with several already-small manual margins below
		   rather than replacing them. */
		--wp--style--block-gap: 0.75rem;
	}

	.vlg-footer-separator {
		margin: 1.25rem 0 1rem;
	}

	.vlg-footer-top {
		grid-template-columns: 1fr;
		text-align: center;
		gap: 1.25rem;
	}

	.vlg-footer-brand__logo img {
		width: 150px;
		margin-inline: auto;
	}

	/* The logo image already contains the wordmark: a large duplicate
	   text title underneath it is redundant on mobile. */
	.vlg-footer-brand__title {
		display: none;
	}

	.vlg-footer-brand__tagline {
		max-width: 320px;
		margin-inline: auto;
		font-size: 15px;
	}

	.vlg-footer-nav-col > .wp-block-heading {
		font-size: 16px !important;
	}

	/* A centered, wrapping row of links (like a boutique-hotel footer)
	   instead of a rigid 2-column grid - reads as one intentional,
	   balanced group rather than two stiff lists, and naturally settles
	   into 2-3 lines depending on how the six labels pack. Each item
	   still needs its own centering forced, because core's Navigation
	   block applies a left-justified flex layout to every nav item
	   (from the block's justifyContent:"left" setting, used for the
	   desktop column), which otherwise wins over simple text-align.

	   Two more overrides confirmed necessary live, via getComputedStyle
	   - both from the desktop column's own orientation:"vertical"
	   setting, which WordPress's own generated classes (.is-vertical
	   etc.) apply with enough specificity to survive into this
	   mobile-only block otherwise: (1) the container was shrinking to
	   fit only its widest single item (~80px) instead of the full
	   column width, so every item had nowhere to sit beside another -
	   width:100% fixes that; (2) flex-direction was still "column" from
	   that same vertical setting, so "wrap" was wrapping into new
	   *columns* (never triggered, since nothing constrained the
	   container's height) instead of new rows - every link rendered on
	   its own line regardless of how much horizontal room existed.
	   flex-direction:row is what actually makes items sit side by side
	   and wrap onto a second/third row. */
	.vlg-footer-nav .wp-block-navigation__container {
		display: flex !important;
		flex-direction: row !important;
		flex-wrap: wrap;
		justify-content: center;
		align-items: center;
		width: 100%;
		column-gap: 22px;
		row-gap: 16px;
	}

	.vlg-footer-nav .wp-block-navigation-item {
		display: flex;
		align-items: center;
		justify-content: center;
		flex: 0 0 auto;
		width: auto;
	}

	/* A small gold dot before every link except the first, instead of
	   plain gaps - reads as one deliberate, boutique-style group of
	   links rather than a bare word list. Placed as a ::before on the
	   item (which travels with its own link when flex-wrap moves it to
	   a new line) rather than an ::after on the previous item, so a
	   dot can never end up orphaned alone at the end of a wrapped row. */
	.vlg-footer-nav .wp-block-navigation-item:not(:first-child)::before {
		content: "";
		width: 4px;
		height: 4px;
		flex-shrink: 0;
		border-radius: 50%;
		background-color: var(--wp--preset--color--gold);
		margin-right: 10px;
	}

	.vlg-footer-nav a {
		font-size: 15px;
		letter-spacing: 0.02em;
	}

	.vlg-footer-contact__title {
		font-size: clamp(30px, 8vw, 32px);
	}

	.vlg-footer-contact a,
	.vlg-footer-contact p {
		font-size: 16px;
	}

	.vlg-footer-bottom {
		flex-direction: column;
		text-align: center;
	}

	.vlg-footer-copyright {
		font-size: 13px;
	}

	.vlg-footer-tagline {
		font-size: 13px;
	}
}

/* -----------------------------------------------------------------------
 * Floating WhatsApp / Zalo buttons
 * Hidden while the mobile menu overlay is open (body.vlg-menu-open, set
 * by assets/js/mobile-menu.js) so they never overlap the full-screen nav.
 * --------------------------------------------------------------------- */

.vlg-floating-buttons {
	position: fixed;
	right: 1rem;
	bottom: 1rem;
	z-index: 90;
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	align-items: flex-end;
	transition: opacity 0.25s ease, visibility 0.25s ease;
}

/* This is a WordPress group block with layout:"default" (flow), so
   WordPress's own global styles also carry a hardcoded (not var()-based
   - confirmed by reading the actual generated rule, so overriding the
   --wp--style--block-gap custom property has no effect on it) rule:
   `:root :where(.is-layout-flow) > * { margin-block: 1.5rem 0 }`. That
   :where() wrapper drops its own specificity to zero, but the bare
   :root before it still gives the whole selector the same specificity
   as a single class, so it was silently adding a real 24px margin-top
   to the second button on top of the flex `gap` above (confirmed live:
   WhatsApp had margin-top:24px that no rule in this file ever set).
   !important is the reliable way to beat a global-styles rule whose
   exact shape/specificity can change between WordPress versions. */
.vlg-floating-btn {
	margin-block: 0 !important;
}

/* Faded out (not display:none, so layout/observer targets stay stable)
   whenever a booking CTA or the footer — both already offering the
   same WhatsApp/Zalo actions directly — is in view; see
   assets/js/floating-buttons.js. */
.vlg-floating-buttons--near-cta {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
	.vlg-floating-buttons {
		transition: none;
	}
}

.vlg-floating-btn {
	-webkit-tap-highlight-color: transparent;
	display: flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.65rem 1rem;
	border-radius: 999px;
	font-weight: 700;
	font-size: 0.9rem;
	box-shadow: 0 4px 14px rgba(13, 43, 33, 0.25);
	transition: transform 0.15s ease;
	text-decoration: none;
}

.vlg-floating-btn:hover {
	transform: translateY(-2px);
}

/* Removed: an infinite box-shadow "attention pulse" on the floating
   buttons (present on every page). box-shadow animations force a
   repaint every frame instead of running on the compositor - reported
   live as repeated multi-second scroll freezes on real hardware.
   Not worth it for a decorative pulse. */

.vlg-floating-btn__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.5rem;
	height: 1.5rem;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.25);
	font-size: 0.85rem;
}

.vlg-floating-btn--whatsapp {
	background-color: #25d366;
	color: #0d2b21;
}

/* Zalo's real brand blue, matching the official mark below. */
.vlg-floating-btn--zalo {
	background-color: #0068ff;
	color: #ffffff;
}

/* The official Zalo mark (assets/images/zalo-icon.svg) already has its
   own rounded-square blue background baked in, so it replaces (rather
   than sits inside) the translucent circle .vlg-floating-btn__icon
   normally uses for WhatsApp's plain glyph. object-fit:cover + a
   circular clip lets the square icon fill the round slot cleanly -
   the cropped corners are the icon's own matching blue, so the seam
   is invisible. */
.vlg-floating-btn__icon--brand {
	background: transparent;
	overflow: hidden;
}

.vlg-floating-btn__icon--brand img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Desktop: icon-only circles at rest (the base/unscoped rules above
   this point were, until now, the ONLY desktop styling that existed -
   an always-visible pill with its label permanently showing - the
   mobile block further down already had its own separate circular
   treatment). Same brand icons/colors/links as before, untouched -
   only size, shape and the reveal-on-hover behavior are new.
   Padding-left never changes between the circle and expanded states:
   only the button's own width (and the label's max-width/opacity)
   transition, so the icon's position is never reset mid-animation -
   it simply travels left as the box grows, which combined with the
   parent's align-items:flex-end (already fixes each button's RIGHT
   edge, unchanged since this component was first built) is what makes
   the whole button expand to the left with its right edge planted. */
@media (min-width: 900px) {
	.vlg-floating-buttons {
		/* More breathing room between the two - was 10px, reads more
		   deliberate/premium at 14px than merely "close together". */
		gap: 14px;
	}

	.vlg-floating-btn {
		/* A touch smaller (was 56px) and a thin ivory ring instead of
		   just a bare color circle - the ring gives each button a clean
		   edge against any part of the page behind it and reads as a
		   considered detail rather than a plain flat dot. box-sizing:
		   border-box keeps the ring INSIDE the 52px - it never grows the
		   button past the size set here. */
		width: 52px;
		height: 52px;
		padding: 0 0 0 13px;
		box-sizing: border-box;
		border: 2px solid rgba(255, 253, 248, 0.9);
		/* Softer and more diffuse than the base rule's shadow (used
		   as-is on mobile) - a tighter, darker shadow read as heavier/
		   "cheaper"; a wider, lighter one feels more like a refined
		   floating card. */
		box-shadow: 0 6px 18px rgba(13, 43, 33, 0.2);
		justify-content: flex-start;
		overflow: hidden;
		transition: width 0.25s ease, transform 0.15s ease;
	}

	.vlg-floating-btn__icon {
		flex-shrink: 0;
		/* Slightly smaller than the base 1.5rem, proportional to the
		   smaller 52px circle above. */
		width: 1.35rem;
		height: 1.35rem;
	}

	.vlg-floating-btn__label {
		display: inline-block;
		max-width: 0;
		opacity: 0;
		overflow: hidden;
		white-space: nowrap;
		margin-left: 0.6rem;
		transition: max-width 0.25s ease, opacity 0.2s ease;
	}

	/* Expansion (and the label it reveals) only for pointers that can
	   truly hover - on a touchscreen "desktop" (e.g. a touch laptop),
	   a tap should just open the chat directly rather than risk a
	   stuck-expanded button with no real hover to un-stick it. Each
	   button's own hover width only needs to fit its own label -
	   Zalo's shorter than WhatsApp's - so neither pill is wider than
	   it has to be. */
	@media (hover: hover) {
		.vlg-floating-btn--zalo:hover {
			width: 124px;
		}

		.vlg-floating-btn--whatsapp:hover {
			width: 166px;
		}

		.vlg-floating-btn:hover .vlg-floating-btn__label {
			max-width: 110px;
			opacity: 1;
		}
	}

	@media (prefers-reduced-motion: reduce) {
		.vlg-floating-btn,
		.vlg-floating-btn__label {
			transition: none;
		}
	}
}

/* Mobile: compact circular icon-only buttons (no text label), hidden
   completely while the mobile menu overlay is open. */
@media (max-width: 899px) {
	.vlg-floating-buttons {
		right: 14px;
		bottom: 18px;
		gap: 8px;
	}

	.vlg-floating-btn {
		width: 50px;
		height: 50px;
		padding: 0;
		justify-content: center;
		box-shadow: 0 3px 10px rgba(13, 43, 33, 0.2);
	}

	.vlg-floating-btn__label {
		display: none;
	}

	.vlg-floating-btn__icon {
		width: 26px;
		height: 26px;
		background: transparent;
	}

	.vlg-floating-btn__icon svg {
		display: block;
		width: 100%;
		height: 100%;
	}
}

/* Scoped to mobile only: the floating buttons must never be affected
   by the mobile menu's open/closed state on desktop, regardless of
   whether body.vlg-menu-open is ever (incorrectly) present there. */
@media (max-width: 899px) {
	body.vlg-menu-open .vlg-floating-buttons {
		display: none;
	}
}

/* -----------------------------------------------------------------------
 * Premium detail — custom cursor dot on card hover (desktop only).
 * assets/js/custom-cursor.js creates .vlg-cursor-dot and adds
 * .vlg-cursor-target to the hoverable cards; both are absent unless
 * that script actually decided to run (fine pointer, desktop width,
 * no reduced-motion), so there is no dependency on this CSS elsewhere.
 * --------------------------------------------------------------------- */

.vlg-cursor-dot {
	position: fixed;
	top: 0;
	left: 0;
	width: 10px;
	height: 10px;
	margin: -5px 0 0 -5px;
	border-radius: 50%;
	background-color: var(--wp--preset--color--gold);
	opacity: 0;
	pointer-events: none;
	z-index: 999999;
	transition: opacity 0.2s ease, width 0.2s ease, height 0.2s ease, margin 0.2s ease;
	will-change: transform;
}

.vlg-cursor-dot--active {
	opacity: 0.85;
	width: 36px;
	height: 36px;
	margin: -18px 0 0 -18px;
	background-color: transparent;
	border: 1.5px solid var(--wp--preset--color--gold);
}

.vlg-cursor-target {
	cursor: none;
}

/* Removed: the scroll-triggered fade-up effect (assets/js/scroll-
   reveal.js, disabled in functions.php) and its .vlg-reveal/.vlg-in-
   view classes - one of two effects present on every page during
   scroll, disabled as a precaution alongside the floating-button
   pulse after repeated live reports of multi-second scroll freezes. */

/* Removed: background-attachment:fixed on the Home hero (a subtle
   desktop parallax effect) caused real scroll stutter/freezes on some
   PCs - browsers must repaint a "fixed" background on every scroll
   tick instead of just compositing it, which is a well-known
   performance pitfall for a full-viewport image like this hero.
   Reported live by the site owner ("stuck on a section, can't scroll
   for a few seconds"); not worth it for a purely decorative effect. */

/* -----------------------------------------------------------------------
 * Accessibility utility (visually hidden but available to screen readers)
 * --------------------------------------------------------------------- */

.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal;
}

/* -----------------------------------------------------------------------
 * Site Reviews plugin integration (Guest Book + Home).
 *
 * This theme never touches the plugin's own files or its calculated
 * data - the shortcodes below ([site_reviews_summary], [site_reviews],
 * [site_reviews_form]) are the plugin's own official output; everything
 * here only restyles the markup it renders, scoped under theme wrapper
 * classes (.vlg-reviews-*, .vlg-home-reviews__*) so nothing here can
 * leak onto some other, unrelated use of the plugin's classes anywhere
 * else. Selectors lean on the plugin's documented "glsr-" class prefix
 * (its own theming hook, stable across releases) plus a handful of
 * [class*="glsr-..."] attribute selectors so a minor internal class
 * name (e.g. an extra BEM modifier) doesn't silently break the whole
 * rule - and on plain element selectors (input/textarea/button/label)
 * for the form, which work regardless of the plugin's exact class
 * names since a form field is still a form field. No !important: every
 * selector here is deliberately specific enough (wrapper class + real
 * tag/class) to win over the plugin's own lower-specificity defaults.
 * --------------------------------------------------------------------- */

.vlg-reviews-summary,
.vlg-home-reviews__summary {
	max-width: 420px;
	margin: 2rem auto 0;
	text-align: center;
}

.vlg-reviews-summary .glsr-summary,
.vlg-home-reviews__summary .glsr-summary {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.4rem;
	padding: 2rem 1.5rem;
	background-color: var(--wp--preset--color--card-background);
	border: 1px solid var(--wp--preset--color--light-border);
	border-radius: 16px;
	box-shadow: 0 4px 14px rgba(13, 43, 33, 0.08);
}

.vlg-reviews-summary .glsr-star-rating,
.vlg-home-reviews__summary .glsr-star-rating,
.vlg-reviews-list .glsr-star-rating,
.vlg-home-reviews__list .glsr-star-rating {
	color: var(--wp--preset--color--gold);
	font-size: 1.4rem;
}

.vlg-reviews-summary .glsr-summary-rating,
.vlg-home-reviews__summary .glsr-summary-rating {
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.75rem;
	font-weight: 600;
	color: var(--wp--preset--color--dark-green);
}

.vlg-reviews-summary [class*="glsr-summary-text"],
.vlg-home-reviews__summary [class*="glsr-summary-text"] {
	display: none;
}

/* The plugin's own summary widget stamps the real, live review count on
   data-reviews (confirmed live: <div class="glsr-star-rating glsr-stars"
   data-rating="0" data-reviews="0">) - a genuinely dynamic hook, not a
   guess, that needs no PHP/JS to read.
   IMPORTANT: every :has() below matches on the full
   ".glsr-summary-stars .glsr-star-rating.glsr-stars[data-reviews="0"]"
   selector, never a bare "[data-reviews=...]" or even the bare
   ".glsr-star-rating.glsr-stars[data-reviews=...]" - two other places
   in the plugin's own markup reuse those same class names/attribute
   with an unrelated meaning: the per-star-level breakdown bars
   (.glsr-summary-bar-percent, e.g. data-reviews="0" for the 4-star row
   when every real review is 5-star) and, once real reviews exist, each
   individual review card's OWN star display (each one is also a
   ".glsr-star-rating.glsr-stars" with data-reviews="0", since that
   attribute isn't meaningful for a single review). Both false-matched
   "empty" even with 5 real reviews present, confirmed live on
   vinhlocalguide.com (v1.18.3 bug, fixed here) - .glsr-summary-stars
   only ever wraps the one real aggregate widget, so scoping through it
   is what actually disambiguates the three. Confirmed live: exactly one
   ".glsr-summary-stars .glsr-star-rating.glsr-stars[data-reviews]"
   exists per page, always the real aggregate.
   The rating-breakdown bars are hidden unconditionally: the brief asks
   for "average + stars + count", never a statistics table. In their
   place, a compact "★★★★★ 4.9 - Based on 24 traveler reviews" line is
   built entirely from real plugin output: the star widget is reused as
   is (just recolored/resized), the number comes from the plugin's own
   .glsr-tag-value, and the count is read straight off data-reviews via
   CSS attr() - never a hardcoded figure. */
.vlg-reviews-summary .glsr-summary-percentages,
.vlg-home-reviews__summary .glsr-summary-percentages {
	display: none;
}

.vlg-reviews-summary .glsr-star-rating.glsr-stars::after,
.vlg-home-reviews__summary .glsr-star-rating.glsr-stars::after {
	/* Two spaces after the hex escape are deliberate: CSS consumes a
	   single trailing space as the escape's own terminator, so only one
	   space renders after "\00b7" would otherwise print "·Based" with
	   no gap - confirmed live on vinhlocalguide.com. */
	content: " \00b7  Based on " attr(data-reviews) " traveler reviews";
	display: block;
	margin-top: 0.35rem;
	font-family: var(--wp--preset--font-family--body);
	font-size: 0.85rem;
	font-weight: 400;
	letter-spacing: normal;
	color: var(--wp--preset--color--secondary-text);
}

.vlg-reviews-summary .glsr-star-rating.glsr-stars[data-reviews="1"]::after,
.vlg-home-reviews__summary .glsr-star-rating.glsr-stars[data-reviews="1"]::after {
	content: " \00b7  Based on 1 traveler review";
}

.vlg-reviews-empty {
	display: none;
}

/* Hide the plugin's whole summary card (not just the number/stars
   inside it) while count is zero - leaving only its background/padding
   behind with nothing in it would look like an empty broken card
   stacked above our own .vlg-reviews-empty message. */
.vlg-reviews-summary:has(.glsr-summary-stars .glsr-star-rating.glsr-stars[data-reviews="0"]) .glsr-summary-wrap,
.vlg-home-reviews__summary:has(.glsr-summary-stars .glsr-star-rating.glsr-stars[data-reviews="0"]) .glsr-summary-wrap {
	display: none;
}

.vlg-reviews-summary:has(.glsr-summary-stars .glsr-star-rating.glsr-stars[data-reviews="0"]) .vlg-reviews-empty,
.vlg-home-reviews__summary:has(.glsr-summary-stars .glsr-star-rating.glsr-stars[data-reviews="0"]) .vlg-reviews-empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.35rem;
}

.vlg-reviews-empty__stars {
	margin: 0;
	font-size: 1.1rem;
	letter-spacing: 0.2em;
	color: var(--wp--preset--color--gold);
}

.vlg-reviews-empty__title {
	margin: 0.25rem 0 0;
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.25rem;
	font-weight: 600;
	color: var(--wp--preset--color--dark-green);
}

.vlg-reviews-empty__text {
	margin: 0;
	font-size: 0.9rem;
	color: var(--wp--preset--color--secondary-text);
}

.vlg-reviews-empty__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	margin-top: 0.75rem;
	min-height: 44px;
	padding: 0 1.5rem;
	background-color: var(--wp--preset--color--gold);
	color: var(--wp--preset--color--dark-green);
	font-family: var(--wp--preset--font-family--body);
	font-weight: 700;
	border-radius: 999px;
	transition: background-color 0.2s ease;
}

.vlg-reviews-empty__link:hover {
	background-color: var(--wp--preset--color--gold-hover);
}

.vlg-reviews-empty__link:focus-visible {
	outline: 2px solid var(--wp--preset--color--gold-hover);
	outline-offset: 2px;
}

/* No real reviews yet: the plugin's own list shortcode only prints one
   plain sentence in that state (no cards to lay out) - the summary card
   above already carries the premium empty-state message, so the list
   block underneath is redundant while count is zero. */
/* Zero reviews: the "Read Traveler Reviews" + discreet "Leave a Review"
   row is redundant with (and, on mobile, sits right on top of) the
   empty-state's own "Leave a Review" button above - there is nothing
   to read yet, and showing both reads as two competing CTAs. The
   moment a real review lands, data-reviews stops being "0" and this
   whole row reappears automatically alongside the real review list. */
#traveler-reviews:has(.glsr-summary-stars .glsr-star-rating.glsr-stars[data-reviews="0"]) .vlg-reviews-list,
.vlg-home-reviews:has(.glsr-summary-stars .glsr-star-rating.glsr-stars[data-reviews="0"]) .vlg-home-reviews__list,
.vlg-home-reviews:has(.glsr-summary-stars .glsr-star-rating.glsr-stars[data-reviews="0"]) .vlg-home-reviews__actions {
	display: none;
}

/* Safety net: [site_reviews assigned_posts="0" count="2"] on Home is
   confirmed live (5 real reviews) to render every assigned_posts="0"
   review rather than stopping at 2 - an interaction between
   assigned_posts="0" and the plugin's own count/pagination handling,
   not a caching artifact (reproduced with a cache-busted URL). Capping
   visually here is a theme-only fix (no plugin file touched, no query
   changed) and is safe specifically because Home has no "Load more"
   pagination to interfere with - this rule must NOT be copied onto the
   paginated Guest Book list, since it would permanently hide any
   review a real "Load more" click legitimately appends. */
.vlg-home-reviews__list .glsr-review:nth-of-type(n + 3) {
	display: none;
}

/* Review cards - deliberately no gold left-border (the site has moved
   away from that motif); a small centered top rule instead, matching
   the same quiet-accent language used elsewhere on the site. */
.vlg-reviews-list .glsr-reviews,
.vlg-home-reviews__list .glsr-reviews {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1.5rem;
	margin-top: 2.5rem;
	list-style: none;
	padding: 0;
}

.vlg-home-reviews__list .glsr-reviews {
	grid-template-columns: repeat(2, 1fr);
	max-width: 900px;
	margin-inline: auto;
}

@media (min-width: 900px) and (max-width: 1199px) {
	.vlg-reviews-list .glsr-reviews {
		grid-template-columns: repeat(2, 1fr);
	}
}

.vlg-reviews-list .glsr-review,
.vlg-home-reviews__list .glsr-review {
	position: relative;
	background-color: var(--wp--preset--color--card-background);
	border: 1px solid var(--wp--preset--color--light-border);
	border-radius: 16px;
	box-shadow: 0 4px 14px rgba(13, 43, 33, 0.08);
	padding: 1.75rem 2rem;
}

.vlg-reviews-list .glsr-review::before,
.vlg-home-reviews__list .glsr-review::before {
	content: "";
	display: block;
	width: 32px;
	height: 3px;
	margin-bottom: 1rem;
	background-color: var(--wp--preset--color--gold);
	border-radius: 2px;
}

.vlg-reviews-list [class*="glsr-review-author"],
.vlg-home-reviews__list [class*="glsr-review-author"] {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 600;
	color: var(--wp--preset--color--dark-green);
}

.vlg-reviews-list [class*="glsr-review-date"],
.vlg-home-reviews__list [class*="glsr-review-date"] {
	font-size: 0.85rem;
	color: var(--wp--preset--color--secondary-text);
}

.vlg-reviews-list [class*="glsr-review-content"],
.vlg-reviews-list [class*="glsr-review-response"],
.vlg-home-reviews__list [class*="glsr-review-content"],
.vlg-home-reviews__list [class*="glsr-review-response"] {
	margin-top: 0.75rem;
	color: var(--wp--preset--color--main-dark-text);
	line-height: 1.6;
}

/* "Load more" (pagination="ajax") - styled as the site's quiet
   secondary button rather than the plugin's own default look. */
.vlg-reviews-list [class*="glsr-button"] {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	margin: 2rem auto 0;
	min-height: 48px;
	padding: 0 1.75rem;
	background-color: transparent;
	border: 2px solid var(--wp--preset--color--gold);
	border-radius: 999px;
	color: var(--wp--preset--color--dark-green);
	font-family: var(--wp--preset--font-family--body);
	font-weight: 700;
	cursor: pointer;
	transition: background-color 0.2s ease, color 0.2s ease;
}

.vlg-reviews-list [class*="glsr-button"]:hover {
	background-color: var(--wp--preset--color--gold);
}

.vlg-reviews-list [class*="glsr-button"]:focus-visible {
	outline: 2px solid var(--wp--preset--color--gold-hover);
	outline-offset: 2px;
}

@media (max-width: 899px) {
	.vlg-reviews-list .glsr-reviews,
	.vlg-home-reviews__list .glsr-reviews {
		grid-template-columns: 1fr;
		gap: 1rem;
		margin-top: 2rem;
	}

	.vlg-reviews-list .glsr-review,
	.vlg-home-reviews__list .glsr-review {
		padding: 1.5rem 1.25rem;
	}

	.vlg-reviews-summary .glsr-summary,
	.vlg-home-reviews__summary .glsr-summary {
		padding: 1.5rem 1.25rem;
	}
}

/* Home "Loved by Travelers": the primary "Read Traveler Reviews" button
   and the quieter "Leave a Review" text link that sits beside it. Flex
   + wrap so they sit side by side when there's room and stack cleanly
   with even spacing on narrow screens, instead of needing a separate
   mobile-only rule. */
.vlg-home-reviews__actions {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 1.5rem;
	margin-top: 2rem;
}

/* A quiet secondary action - gold underline on dark-green text, no
   fill, no border-radius pill shape - so it never competes with the
   solid-gold primary button next to it. */
.vlg-link-discreet {
	display: inline-flex;
	align-items: center;
	padding: 0.6rem 0.25rem;
	font-family: var(--wp--preset--font-family--body);
	font-weight: 700;
	font-size: 0.95rem;
	color: var(--wp--preset--color--dark-green);
	border-bottom: 1px solid var(--wp--preset--color--gold);
	line-height: 1.2;
	transition: color 0.2s ease, border-color 0.2s ease;
}

.vlg-link-discreet:hover,
.vlg-link-discreet:focus-visible {
	color: var(--wp--preset--color--gold-hover);
	border-bottom-color: var(--wp--preset--color--gold-hover);
}

/* Anchor targets under the sticky header (see .vlg-site-header) - a
   plain #anchor jump would otherwise land with the section heading
   tucked behind the fixed header bar. CSS-only, no JS needed. */
#traveler-reviews,
#share-your-experience {
	scroll-margin-top: calc(var(--vlg-header-height-mobile) + 16px);
}

@media (min-width: 900px) {
	#traveler-reviews,
	#share-your-experience {
		scroll-margin-top: calc(var(--vlg-header-height) + 16px);
	}
}

/* -----------------------------------------------------------------------
 * Site Reviews submission form ("Share Your Experience", Guest Book).
 *
 * Verified against the plugin's real rendered markup (Site Reviews /
 * Gemini Labs, glsr- prefixed classes - there is no <fieldset> anywhere,
 * every field is a <div class="glsr-field">). The whole form now sits in
 * one premium card (ivory fill, thin border, soft shadow) so it reads as
 * a self-contained section instead of a bare plugin form; only spacing,
 * color and borders are touched here - never the plugin's own field
 * logic, required attributes, or the Turnstile widget itself.
 * --------------------------------------------------------------------- */

#share-your-experience .vlg-lead {
	margin-bottom: 0;
}

.vlg-reviews-form {
	max-width: 720px;
	margin: 1.5rem auto 0;
	background-color: var(--wp--preset--color--card-background);
	border: 1px solid var(--wp--preset--color--light-border);
	border-radius: 22px;
	box-shadow: 0 4px 14px rgba(13, 43, 33, 0.08);
	padding: 2.25rem 2.25rem 2rem;
}

/* Desktop only: Name and Email sit side by side. The plugin's own form
   markup is a flat list of sibling <div class="glsr-field" data-field="...">
   elements (no wrapping row div to hook into), so the trick here is to
   make the whole <form> a 2-column grid and force every field back to
   full width except the two we want paired - using the plugin's own
   data-field attributes, never a class name that could change silently
   on a minor plugin update. */
@media (min-width: 700px) {
	/* The plugin's own CSS (.glsr-default form.glsr-form) already sets
	   display:grid with a single 1fr column at a specificity (2 classes
	   + 1 type) that a plain ".vlg-reviews-form form" loses to regardless
	   of load order - repeating the class selector here is the standard
	   way to out-specify that without resorting to !important. */
	.vlg-reviews-form.vlg-reviews-form form.glsr-form {
		grid-template-columns: 1fr 1fr;
		column-gap: 1.25rem;
	}

	.vlg-reviews-form form.glsr-form > *:not([data-field="name"]):not([data-field="email"]) {
		grid-column: 1 / -1;
	}
}

/* Site Reviews prints several stray empty <p></p> tags between fields
   (after the rating, after error placeholders, after the submit button);
   left alone, these pick up the browser's default paragraph margin and
   add unwanted vertical space. */
.vlg-reviews-form p {
	margin: 0;
}

/* The plugin also prints a <br> after each of its ~10 hidden anti-spam/
   nonce inputs at the very top of the form - confirmed live to total
   ~190px of pure blank space before the rating field even starts, the
   single biggest contributor to the "too much empty space" complaint.
   None of these hidden inputs are visible, so hiding their <br> siblings
   changes nothing functional. */
.vlg-reviews-form br {
	display: none;
}

.vlg-reviews-form label {
	display: block;
	font-family: var(--wp--preset--font-family--body);
	font-weight: 700;
	font-size: 0.9rem;
	color: var(--wp--preset--color--dark-green);
	margin-bottom: 0.35rem;
}

/* Real field wrapper is <div class="glsr-field">, not a <fieldset> -
   this replaces a rule from an earlier round that targeted <fieldset>
   and, per the live markup, never matched anything. */
.vlg-reviews-form .glsr-field {
	margin-bottom: 1.1rem;
}

.vlg-reviews-form .glsr-field-error:empty,
.vlg-reviews-form .glsr-form-message:empty {
	display: none;
}

.vlg-reviews-form .glsr-field-error {
	margin-top: 0.3rem;
	font-size: 0.85rem;
}

.vlg-reviews-form input[type="text"],
.vlg-reviews-form input[type="email"],
.vlg-reviews-form .glsr-input,
.vlg-reviews-form .glsr-textarea,
.vlg-reviews-form textarea {
	display: block;
	width: 100%;
	min-height: 42px;
	background-color: var(--wp--preset--color--ivory-white);
	border: 1px solid var(--wp--preset--color--light-border);
	border-radius: 10px;
	padding: 0.6rem 0.9rem;
	font-family: var(--wp--preset--font-family--body);
	font-size: 0.98rem;
	color: var(--wp--preset--color--main-dark-text);
	transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.vlg-reviews-form textarea,
.vlg-reviews-form .glsr-textarea {
	min-height: 120px;
	resize: vertical;
}

.vlg-reviews-form input[type="text"]:focus,
.vlg-reviews-form input[type="email"]:focus,
.vlg-reviews-form .glsr-input:focus,
.vlg-reviews-form textarea:focus,
.vlg-reviews-form .glsr-textarea:focus {
	outline: none;
	border-color: var(--wp--preset--color--gold);
	box-shadow: 0 0 0 3px rgba(214, 170, 82, 0.18);
}

.vlg-reviews-form ::placeholder {
	color: var(--wp--preset--color--secondary-text);
	opacity: 0.75;
}

/* Rating: keep the gold color but bring the stars down from the
   plugin's default (measured 32px on the live site) to a size that
   reads as elegant rather than oversized, especially on narrow phones. */
.vlg-reviews-form .glsr-field-rating .glsr-label {
	margin-bottom: 0.5rem;
}

.vlg-reviews-form [class*="glsr-star-rating"] {
	font-size: 1.5rem;
	color: var(--wp--preset--color--gold);
}

.vlg-reviews-form [class*="glsr-star"] {
	cursor: pointer;
}

/* "Titre de votre avis" is the only optional text field (not marked
   glsr-required in the real markup) - kept, per instructions, but made
   visually quieter so it doesn't compete with the required fields. */
.vlg-reviews-form [data-field="title"] label {
	font-weight: 500;
	font-size: 0.85rem;
	color: var(--wp--preset--color--secondary-text);
}

/* Terms/confirmation toggle: only the plugin's own switch color changes
   on :checked - its size, position and markup are never touched, so the
   control keeps working exactly as before. */
.vlg-reviews-form .glsr-field-toggle {
	display: flex;
	align-items: center;
	gap: 0.65rem;
}

.vlg-reviews-form .glsr-field-toggle label {
	font-weight: 400;
	font-size: 0.88rem;
	color: var(--wp--preset--color--main-dark-text);
	margin-bottom: 0;
}

.vlg-reviews-form .glsr-toggle-track {
	background-color: var(--wp--preset--color--light-border);
}

.vlg-reviews-form .glsr-input-toggle:checked + .glsr-toggle-track {
	background-color: var(--wp--preset--color--gold);
}

.vlg-reviews-form button[type="submit"],
.vlg-reviews-form input[type="submit"],
.vlg-reviews-form [class*="glsr-button"] {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: 48px;
	padding: 0 1.5rem;
	margin-top: 1.5rem;
	background-color: var(--wp--preset--color--gold);
	color: var(--wp--preset--color--dark-green);
	font-family: var(--wp--preset--font-family--body);
	font-weight: 700;
	border: none;
	border-radius: 999px;
	cursor: pointer;
	transition: background-color 0.2s ease;
}

.vlg-reviews-form button[type="submit"]:hover,
.vlg-reviews-form input[type="submit"]:hover,
.vlg-reviews-form [class*="glsr-button"]:hover {
	background-color: var(--wp--preset--color--gold-hover);
}

.vlg-reviews-form button[type="submit"]:focus-visible,
.vlg-reviews-form input[type="submit"]:focus-visible,
.vlg-reviews-form [class*="glsr-button"]:focus-visible {
	outline: 2px solid var(--wp--preset--color--gold-hover);
	outline-offset: 2px;
}

/* Cloudflare Turnstile keeps its own configured light theme, size and
   behaviour untouched - the real wrapper is .glsr-captcha-holder (an
   earlier round targeted the generic .cf-turnstile class, which per the
   live markup never matched anything). Only a spacing/overflow safety
   net around the plugin's own widget, clearly separated from the submit
   button, is a theme concern. */
.vlg-reviews-form .glsr-captcha-holder {
	margin-top: 1.5rem;
	padding-top: 1.25rem;
	border-top: 1px solid var(--wp--preset--color--light-border);
	max-width: 100%;
	overflow: hidden;
}

.vlg-reviews-form [class*="glsr-notice"] {
	border-radius: 10px;
	padding: 0.9rem 1.1rem;
	margin-bottom: 1.25rem;
	font-size: 0.95rem;
	line-height: 1.5;
}

.vlg-reviews-form [class*="glsr-notice-success"] {
	background-color: var(--wp--preset--color--light-sage);
	color: var(--wp--preset--color--dark-green);
	border: 1px solid var(--wp--preset--color--gold);
}

.vlg-reviews-form [class*="glsr-notice-error"] {
	background-color: #fbeaea;
	color: #7a2e2e;
	border: 1px solid #d98c8c;
}

@media (max-width: 899px) {
	.vlg-reviews-form {
		margin-top: 1.25rem;
		padding: 1.75rem 1.25rem 1.5rem;
		border-radius: 20px;
	}

	.vlg-reviews-form .glsr-field {
		margin-bottom: 0.9rem;
	}

	.vlg-reviews-form [class*="glsr-star-rating"] {
		font-size: 1.3rem;
	}

	.vlg-reviews-form textarea,
	.vlg-reviews-form .glsr-textarea {
		min-height: 110px;
	}
}

/* -----------------------------------------------------------------------
 * Collapsed "Leave a Review" invitation + reveal (Guest Book).
 *
 * The form card above stays in the markup and fully functional at all
 * times - this only controls whether it is visible. Baseline (no JS)
 * relies purely on :target: #share-your-experience is the same anchor
 * Home/Footer already link to, so a plain click on the toggle (a real
 * <a href="#share-your-experience">) opens the panel with zero script.
 * review-toggle.js (enqueued conditionally) progressively upgrades this
 * with a smoother class-driven open/close, a working Close control and
 * aria-expanded bookkeeping, but never becomes the only way to open it.
 * --------------------------------------------------------------------- */

.vlg-review-invite__stars {
	margin: 0.75rem 0 0;
	font-size: 1.1rem;
	line-height: 1;
	letter-spacing: 0.2em;
	color: var(--wp--preset--color--gold);
}

.vlg-review-invite__cta {
	margin: 1.25rem 0 0;
}

.vlg-review-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 50px;
	padding: 0 1.75rem;
	background-color: var(--wp--preset--color--gold);
	color: var(--wp--preset--color--dark-green);
	font-family: var(--wp--preset--font-family--body);
	font-weight: 700;
	border-radius: 999px;
	transition: background-color 0.2s ease;
}

.vlg-review-toggle:hover {
	background-color: var(--wp--preset--color--gold-hover);
}

.vlg-review-toggle:focus-visible {
	outline: 2px solid var(--wp--preset--color--gold-hover);
	outline-offset: 2px;
}

.vlg-review-form-panel {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows 0.3s ease;
}

#share-your-experience:target .vlg-review-form-panel,
.vlg-review-form-panel.is-open {
	grid-template-rows: 1fr;
}

.vlg-review-form-panel-inner {
	overflow: hidden;
	min-height: 0;
}

/* Once the form is open (either via :target or the JS-driven .is-open
   class), hide the "Leave a Review" toggle - the Close control below
   replaces it, so only one open/close affordance is visible at a time.
   :has() reaches "up and across" from the panel to its earlier sibling,
   which a plain ~ combinator cannot do since .vlg-review-invite__cta
   comes before .vlg-review-form-panel in the markup. */
#share-your-experience:target .vlg-review-invite__cta,
#share-your-experience:has(.vlg-review-form-panel.is-open) .vlg-review-invite__cta {
	display: none;
}

.vlg-review-close {
	display: none;
	margin: 0 0 1.25rem;
	background: none;
	border: none;
	padding: 0;
	font-family: var(--wp--preset--font-family--body);
	font-size: 0.9rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	color: var(--wp--preset--color--secondary-text);
	text-decoration: underline;
	cursor: pointer;
}

.vlg-review-close[hidden] {
	display: none;
}

.vlg-review-form-panel.is-open .vlg-review-close:not([hidden]) {
	display: inline-block;
}

.vlg-review-close:hover {
	color: var(--wp--preset--color--dark-green);
}

.vlg-review-close:focus-visible {
	outline: 2px solid var(--wp--preset--color--gold-hover);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.vlg-review-form-panel {
		transition: none;
	}
}

/* -----------------------------------------------------------------------
 * Privacy Policy (and any future legal page reusing .vlg-legal-content)
 * --------------------------------------------------------------------- */

.vlg-legal-content {
	max-width: 860px;
	margin-inline: auto;
	padding-block: 3rem 5rem;
}

.vlg-legal-content h2 {
	font-size: clamp(24px, 2vw, 28px);
	color: var(--wp--preset--color--dark-green);
	margin-top: 2.5rem;
	margin-bottom: 0.75rem;
}

.vlg-legal-content > h2:first-child {
	margin-top: 0;
}

.vlg-legal-content p {
	color: var(--wp--preset--color--main-dark-text);
	line-height: 1.75;
	margin-bottom: 1.1rem;
}

.vlg-legal-content ul {
	margin: 0 0 1.1rem;
	padding-left: 1.4rem;
	line-height: 1.75;
	color: var(--wp--preset--color--main-dark-text);
}

.vlg-legal-content li {
	margin-bottom: 0.4rem;
}

.vlg-legal-content strong {
	color: var(--wp--preset--color--dark-green);
}

.vlg-legal-content a {
	color: var(--wp--preset--color--gold-hover);
	text-decoration-color: rgba(214, 170, 82, 0.5);
}

.vlg-legal-content a:hover,
.vlg-legal-content a:focus-visible {
	color: var(--wp--preset--color--dark-green);
}

.vlg-legal-content__meta {
	font-size: 0.85rem;
	color: var(--wp--preset--color--secondary-text);
	font-style: italic;
	margin-bottom: 2.5rem !important;
}

@media (max-width: 899px) {
	.vlg-legal-content {
		padding-block: 2rem 3rem;
	}

	.vlg-legal-content h2 {
		font-size: clamp(21px, 5vw, 24px);
		margin-top: 2rem;
	}

	.vlg-legal-content p,
	.vlg-legal-content ul {
		font-size: 15.5px;
	}
}

/* -----------------------------------------------------------------------
 * No-horizontal-overflow safety net
 * --------------------------------------------------------------------- */

html {
	overflow-x: hidden;
}

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