/**
 * Theme Name:     Havenpro Child
 * Author:         Jegtheme
 * Template:       havenpro
 * Text Domain:	   havenpro-child
 * Description:    Havenpro offers a refined, modern layout crafted for Real Estate & Property websites. With its clean structure and intuitive design, it highlights your listings, builds client confidence, and positions your brand as a trusted industry leader.
 * Theme URI:      https://fse.jegtheme.com/havenpro/
 * Author URI:     https://support.jegtheme.com/
 * Version:        1.0.0
 * License:        GNU General Public License v3 or later.
 * License URI:    https://www.gnu.org/licenses/gpl-3.0.html
 * Tags:           grid-layout,block-patterns,block-styles,full-site-editing,editor-style
 */

/* Form fields should only show a validation message once JS actually
   flags an invalid entry, and the submit spinner only while a request
   is in flight. Without that state toggling (no forms backend wired
   up yet) both default to visible, which reads as a broken form. */
.gutenverse-input-select ~ .validation-error,
.main-wrapper .validation-error {
	display: none;
}
.gutenverse-input-submit-loader {
	display: none;
}

/* Home hero search widget: the submit button's pill-shaped wrapper was
   stretching to fill its full column width (via the generic
   .guten-inner-wrap{width:100%} rule) while the button inside only filled
   its own text size, leaving a dead empty pill trailing after it. Scoped
   to this instance's own class so no other wrapper site-wide is affected. */
.guten-fy3I7P,
.guten-fy3I7P .guten-inner-wrap {
	width: fit-content !important;
}

/* Select fields (Location/Type/Price Range, etc.) are meant to be enhanced
   into a custom-styled dropdown by a JS library (Choices.js) that ships
   only with the paid Gutenverse Companion Pro add-on, which isn't
   installed. Without it they fall back to the raw, unstyled native
   browser <select> box. Styling the native element directly here so it
   matches the theme's intended minimal underline look everywhere it's
   used site-wide, instead of leaving it as a default OS dropdown. */
select.gutenverse-input-select {
	-webkit-appearance: none;
	-moz-appearance: none;
	appearance: none;
	background: transparent;
	border: none;
	border-bottom: 1px solid rgba(20, 35, 61, 0.2);
	border-radius: 0;
	width: 100%;
	padding: 8px 22px 8px 0;
	font-size: 15px;
	color: #14233D;
	cursor: pointer;
}
/* The chevron has to live on the wrapping .main-wrapper, not the <select>
   itself — browsers don't render ::after on replaced form elements.
   NOTE: only relevant if Choices.js fails to load (see below for why
   the chevron itself was removed from here). */
.guten-form-input-select .main-wrapper {
	position: relative;
}

/* Same missing-Pro-plugin problem as the select fields: text/email/tel
   inputs and textareas (newsletter email, contact form fields) are meant
   to get the theme's minimal underline treatment but fall back to a
   plain bordered native box without it. The reference theme demo
   (fse.jegtheme.com/havenpro) shows these as transparent-background,
   bottom-border-only fields — matching that here instead of leaving the
   default browser input box. Default (dark-on-light) suits the Contact
   page's light card; the footer newsletter override below flips it for
   its dark navy background. */
input.gutenverse-input,
textarea.gutenverse-input {
	background: transparent;
	border: none;
	border-bottom: 1px solid rgba(20, 35, 61, 0.3);
	border-radius: 0;
	width: 100%;
	padding: 8px 4px;
	font-size: 15px;
	color: #14233D;
}
input.gutenverse-input::placeholder,
textarea.gutenverse-input::placeholder {
	color: rgba(20, 35, 61, 0.55);
}
/* Footer newsletter sits on the dark navy .guten-yfR8BF section — light
   underline and text instead of the dark default above. */
.guten-yfR8BF input.gutenverse-input {
	border-bottom-color: rgba(255, 255, 255, 0.4);
	color: #fff;
}
.guten-yfR8BF input.gutenverse-input::placeholder {
	color: rgba(255, 255, 255, 0.7);
}

/* The theme's "full-width" template (used by Privacy Policy, Terms, and
   Disclaimer) renders post-content with no top offset or width
   constraint at all, so it collides with the fixed header and runs
   edge-to-edge. Every other page using this template has its own hero
   pattern providing that clearance; these plain content pages don't,
   so add it directly. IMPORTANT: every page on the site shares this
   same .guten-post-content wrapper (it's the generic block that renders
   a page's body), so this must be scoped to just these 3 legal pages
   via their page-id-* body class — an unscoped rule here previously
   capped the ENTIRE site (Home, About, everything) to 860px wide on
   any screen wider than that, which is the bug that was just reported. */
.page-id-67 .guten-post-content,
.page-id-68 .guten-post-content,
.page-id-69 .guten-post-content {
	max-width: 860px;
	margin: 0 auto;
	padding: 160px 24px 100px;
}
.page-id-67 .guten-post-content h1,
.page-id-68 .guten-post-content h1,
.page-id-69 .guten-post-content h1 {
	color: #14233D;
	margin-bottom: 8px;
}
.page-id-67 .guten-post-content h2,
.page-id-68 .guten-post-content h2,
.page-id-69 .guten-post-content h2 {
	color: #14233D;
	margin-top: 36px;
	margin-bottom: 12px;
}
.page-id-67 .guten-post-content p,
.page-id-67 .guten-post-content li,
.page-id-68 .guten-post-content p,
.page-id-68 .guten-post-content li,
.page-id-69 .guten-post-content p,
.page-id-69 .guten-post-content li {
	margin-bottom: 12px;
	line-height: 1.6;
}

/* Stat counters ("Years of Experience", "Properties Sold", etc.) are
   pure JS count-up animations with zero static fallback text — the
   <span> is empty in the raw HTML and relies entirely on the same
   broken frontend.js to fill in a number. That part is expected.
   What's NOT expected: the Fun_Fact block's own PHP render_callback
   hardcodes data-safe="25"/"9"/"150" regardless of the safeNumber
   value actually stored in the page content — confirmed by comparing
   parse_blocks() (correct, edited values) against do_blocks() output
   (still the theme's original demo numbers) in isolation. This is a
   bug inside the third-party plugin's rendering, not a caching or
   content issue, so content edits alone can't fix it. Overriding the
   displayed number directly per block instance (element IDs are
   reused identically across Home and About) instead of via data-safe. */
/* The animated counter widget renders more than just the empty
   .number span — there's also a separate "0" placeholder digit from
   its odometer-style animation that stays stuck at its starting frame
   since the JS that would animate it never runs. Rather than chase
   every piece it renders, hide all of the widget's own number output
   and replace the whole thing with one clean static value. */
.guten-rWz5q9 .number-wrapper > *,
.guten-AUEx6n .number-wrapper > *,
.guten-9F9C4v .number-wrapper > *,
.guten-Ja5WyB .number-wrapper > * {
	display: none !important;
}
.guten-rWz5q9 .number-wrapper::after {
	content: "3+";
}
.guten-AUEx6n .number-wrapper::after {
	content: "45+";
}
.guten-9F9C4v .number-wrapper::after {
	content: "60+";
}
.guten-Ja5WyB .number-wrapper::after {
	content: "60+";
}

/* Scroll-reveal animations ("fadeInUp" etc.) rely on JS removing the
   guten-element-hide class when an element scrolls into view. That JS
   path is broken sitewide (a real bug in the theme's bundled frontend.js:
   it throws "addFilter is not a function" and never completes), so any
   element still carrying guten-element-hide stays permanently
   visibility:hidden — including the homepage's main hero headline and
   the FAQ accordion questions/answers. Since the JS can't be relied on,
   force every such element visible unconditionally; this sacrifices the
   fade-in entrance animation but guarantees the content is never
   silently invisible. */
.guten-element-hide {
	visibility: visible !important;
}
/* The visibility:hidden gate above is only half of it — these elements
   also carry a CSS animation (fadeInUp etc.) whose 0% keyframe is
   opacity:0, and the JS that's supposed to trigger the animation to
   actually play never runs (same broken frontend.js). Without that
   trigger the element sits frozen at the animation's opacity:0 starting
   state forever. Removing the animation outright guarantees the content
   just shows immediately instead of staying invisible. */
.animated.guten-element-hide {
	animation: none !important;
	opacity: 1 !important;
	transform: none !important;
}

/* Accordion (FAQ, Properties "Everything You Need to Know"): an "active"
   item's .accordion-body defaults to height:0;overflow:hidden and relies
   entirely on JS to measure its content and set an inline pixel height
   to reveal it — no height is ever server-rendered. Same broken
   frontend.js as the scroll-reveal issue above means that measurement
   sometimes never runs (or runs against a stale/zero measurement),
   leaving an "active" item's real answer text clipped to near-zero
   height — it's still there and still gets painted, just squeezed into
   a couple of visible pixels, which reads as faint illegible text
   rather than fully hidden. height:auto removes the dependency on JS
   entirely for whichever item already carries the "active" class. */
.accordion-item.active .accordion-body {
	height: auto !important;
}

/* Home hero headline: white text with only a 10%-opacity shadow reads
   fine against the theme's original dark villa photo, but against our
   bright Toronto sky it has almost no contrast (barely legible). Give it
   a stronger, still-subtle dark shadow rather than a glow/halo. */
.guten-zvMTIB {
	text-shadow: 0 2px 10px rgba(0, 0, 0, 0.6), 0 1px 3px rgba(0, 0, 0, 0.5) !important;
}

/* About page "01/02/03" feature list: items 01 and 02 render fine, but
   03 consistently renders washed-out/faint despite byte-identical
   computed CSS (color, opacity, font, weight, blend-mode, no overlay
   element anywhere in the stack at that point — verified directly via
   elementsFromPoint). Root cause: the three items live inside
   .guten-e05Zpr, a fixed 400px-tall viewport (unique to this page) with
   a plain :hover{transform:translateY(-480px)} reveal — 01/02 show at
   rest, hovering shifts the strip up to reveal 03, and item 03's
   resting position sits partly under a decorative white-to-transparent
   gradient fade mask meant to sell the "scrolling into view" illusion.
   That's a bad pattern for a client-facing static page regardless of
   the exact rendering quirk: it requires discovering a hover target
   that gives no visual affordance, so most visitors would never see 03
   clearly at all. Removing the fixed height/clip/hover-shift entirely
   makes all three items simply visible at once, same as 01/02. */
.guten-e05Zpr.guten-element {
	height: auto !important;
}
.guten-e05Zpr {
	overflow: visible !important;
	transform: none !important;
}
/* With the fixed-height ticker removed above, the 01-05 list is now
   taller than the portrait photo in the column next to it. This
   section's own "align-stretch overflow-hidden" (Gutenverse utility
   classes, matching flex columns to the same height) then clipped
   whatever ran past the photo's height — item 05 "Innovative
   Standards" was getting the exact same partial-clip treatment 03 had
   before. The photo column doesn't need to match the text column's
   height (nothing else in this row depends on equal heights), so let
   the section overflow normally instead of clipping to the shorter
   column. */
.guten-A79o7u {
	overflow: visible !important;
}

/* Header "Contact Our Agent" widget: the icon-box's .body-inner always
   gets a white card background by default (var(--guten-bg-color), a
   plugin-wide baseline), which made the white title/phone text on it
   invisible — same bug exists in the official theme demo itself. Rather
   than darken the text to fit an unwanted white card, remove the card
   and keep the text white, matching how the nav links sit directly on
   the transparent header with no card behind them either. */
.guten-R92JQG .body-inner {
	background: transparent !important;
	box-shadow: none !important;
}
.guten-R92JQG .body-title,
.guten-AFC9HU .guten-button span {
	color: #fff !important;
	text-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
}

/* Logo: the reference theme's header/footer logo is white, and ours was
   still the navy version — barely readable in the dark navy footer, and
   inconsistent with the reference's look in the header. The logo is a
   flat two-tone raster (navy + mid-blue), so brightness(0) collapses it
   to a solid black silhouette (alpha preserved) and invert(1) flips that
   to solid white — the standard trick for recoloring a raster logo
   without a separate white-only source asset. Drop-shadow keeps it
   legible over lighter parts of hero photos, same reasoning as the
   hero headline's text-shadow. */
img[src*="cloudhous-logo-horizontal"] {
	filter: brightness(0) invert(1) drop-shadow(0 1px 4px rgba(0, 0, 0, 0.5));
}

/* Property card "brand" badges (Blossom, Leafe, Terra, Minty, Dune,
   Greenish, ProNature): leftover theme-demo watermark logos pulled
   directly from designer.gutenverse.com, never swapped for anything of
   ours — a lotus/leaf icon reading "Blossom" on a "Luxury Beach House"
   card makes no sense for a real estate listing, so hide them outright
   rather than invent a fake alternative brand mark. */
img[src*="blossom-logo.webp"],
img[src*="logo-leaf.webp"],
img[src*="terra-logo-client.webp"],
img[src*="minty-logo.webp"],
img[src*="logo-dune.webp"],
img[src*="greenish-logo.webp"],
img[src*="pronature.webp"] {
	display: none !important;
}

/* Choices.js dropdown list: its width matches the (fairly narrow)
   closed select box, so longer option text like "$1,500,000 -
   $3,000,000" wraps awkwardly across multiple lines. Let the open list
   size to its content instead of staying pinned to the closed width. */
.guten-form-input-select .choices__list--dropdown {
	width: max-content;
	min-width: 100%;
	max-width: 260px;
}
.guten-form-input-select .choices__list--dropdown .choices__item {
	white-space: nowrap;
}

/* The Choices.js library ships with only its own bare default look
   (small, square-cornered, #f9f9f9 grey box) since this theme never
   included styling for it beyond the CSS variables the paid Companion
   Pro add-on would normally supply — the closed Location/Type/Price
   Range fields on the homepage search widget were rendering as plain,
   unstyled input boxes instead of matching the site's premium look.
   Restyling the closed control directly to a clean rounded card that
   matches the search widget's own rounded/blurred container. */
.guten-form-input-select .choices__inner {
	background-color: #fff;
	border: none;
	border-radius: 14px;
	min-height: 56px;
	padding: 16px 40px 16px 20px;
	font-size: 15px;
	box-shadow: 0 1px 4px rgba(20, 35, 61, 0.1);
}
.guten-form-input-select .choices__list--single {
	padding: 0;
}
.guten-form-input-select .choices__list--single .choices__item {
	color: #14233D;
}
.guten-form-input-select .choices__placeholder {
	color: rgba(20, 35, 61, 0.55);
	opacity: 1;
}
.guten-form-input-select .choices__list--dropdown {
	border-radius: 12px;
	border: none;
	box-shadow: 0 8px 24px rgba(20, 35, 61, 0.16);
	margin-top: 6px;
	overflow: hidden;
}
.guten-form-input-select .choices__list--dropdown .choices__item--selectable {
	padding: 12px 16px;
	color: #14233D;
}
.guten-form-input-select .choices__list--dropdown .choices__item--selectable.is-highlighted {
	background-color: rgba(61, 125, 203, 0.1);
}
/* Choices.js ships its own dropdown-arrow indicator built in
   (.choices[data-type*=select-one]:after, a plain CSS-triangle) — our
   separate ::after chevron on .main-wrapper (originally added as a
   fallback for the raw, pre-Choices native <select>) was rendering at
   the same time, right on top of it, producing a visible double-arrow.
   Now that Choices is confirmed working site-wide, drop our chevron
   entirely and just restyle Choices' own triangle to match the site's
   navy instead of its default mid-grey. */
.guten-form-input-select .choices[data-type*="select-one"]:after {
	border-top-color: #14233D;
	right: 20px;
}
.guten-form-input-select .choices[data-type*="select-one"].is-open:after {
	border-color: transparent transparent #14233D;
}

/* Home hero video background: replaces the static photo with a looping
   muted YouTube embed, matching the "video hero" treatment premium
   real estate sites (including the foxmarin.ca reference) use. Sits
   behind the existing dark gradient overlay so hero text stays legible
   exactly as before — only the backdrop changed. The static background
   image on .guten-44jGcG remains as the poster frame while the video
   loads and as the mobile fallback (video backgrounds are skipped on
   small screens: heavier to load and rarely worth it on mobile data). */
.guten-44jGcG {
	position: relative;
}
/* IMPORTANT: overflow:hidden must live on this background-only layer, not
   on .guten-44jGcG itself. That section also contains the foreground
   search widget, and .guten-44jGcG is reused as the hero section ID on
   EVERY page (Home, About, Properties, etc, confirmed via DB query) — an
   earlier version put overflow:hidden on the section, which correctly
   clipped the video to the section's rounded corners but also silently
   clipped the Choices.js price/type/location dropdown list any time it
   was opened, since an open dropdown is a position:absolute descendant
   of this same overflow:hidden ancestor. border-radius:inherit keeps the
   video clipped to whatever rounded-corner shape each page's own hero
   instance uses (set per-instance by Gutenverse's own inline style)
   without needing overflow:hidden up on the section. */
.guten-hero-video-bg {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	overflow: hidden;
	border-radius: inherit;
	z-index: 0;
	pointer-events: none;
}
.guten-hero-video-bg iframe {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 100vw;
	height: 56.25vw; /* 16:9 */
	min-height: 100%;
	min-width: 177.78vh; /* 16:9 */
	transform: translate(-50%, -50%);
	/* Hidden until hero-video-loop.js confirms real playback (see that
	   file for why) — the section's own static background image is the
	   poster underneath, so this never leaves a visible gap. */
	opacity: 0;
	transition: opacity 0.4s ease;
}
.guten-hero-video-bg.is-playing iframe {
	opacity: 1;
}
.guten-44jGcG .guten-background-overlay {
	z-index: 1;
}
.guten-44jGcG > .guten-container {
	position: relative;
	z-index: 2;
}
@media (max-width: 782px) {
	.guten-hero-video-bg {
		display: none;
	}
}

/* ============================================================
 * PROPERTY LISTINGS SYSTEM — see functions.php for the `property`
 * post type, grid shortcode, and single-property template that
 * these classes belong to.
 * ============================================================ */

.cloudhous-property-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 24px;
	margin: 24px 0;
}
@media (max-width: 900px) {
	.cloudhous-property-grid {
		grid-template-columns: 1fr;
	}
}
.cloudhous-property-card {
	display: block;
	text-decoration: none;
	border-radius: 16px;
	overflow: hidden;
	box-shadow: 0 4px 16px rgba(20, 35, 61, 0.12);
	background: #fff;
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.cloudhous-property-card:hover {
	transform: translateY(-4px);
	box-shadow: 0 12px 28px rgba(20, 35, 61, 0.18);
}
.cloudhous-property-card-img {
	height: 260px;
	background-size: cover;
	background-position: center;
	position: relative;
	display: flex;
	align-items: flex-end;
	padding: 20px;
}
.cloudhous-property-card-img::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0.75) 100%);
	z-index: 0;
}
.cloudhous-property-card-title {
	position: relative;
	z-index: 1;
	color: #fff;
	font-family: var(--gutenverse-font-family-feature, "Michroma");
	font-size: 20px;
}
.cloudhous-property-card-body {
	padding: 20px;
}
.cloudhous-property-card-location {
	display: block;
	color: #3D7DCB;
	font-size: 14px;
	margin-bottom: 8px;
}
.cloudhous-property-card-body p {
	color: rgba(20, 35, 61, 0.65);
	font-size: 15px;
	line-height: 1.5;
	margin-bottom: 16px;
}
.cloudhous-property-card-footer {
	display: flex;
	align-items: center;
	justify-content: space-between;
}
.cloudhous-property-card-price {
	font-family: var(--gutenverse-font-family-feature, "Michroma");
	color: #14233D;
	font-size: 17px;
}
.cloudhous-property-card-btn {
	color: #3D7DCB;
	font-size: 14px;
	font-weight: 600;
}

.cloudhous-property-single {
	max-width: 100%;
}
.cloudhous-property-hero {
	position: relative;
	height: 420px;
	background-size: cover;
	background-position: center;
	display: flex;
	align-items: flex-end;
	border-radius: 0 0 40px 40px;
	overflow: hidden;
}
.cloudhous-property-hero-overlay {
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.75) 100%);
}
.cloudhous-property-hero-content {
	position: relative;
	z-index: 1;
	padding: 40px 60px;
	color: #fff;
}
.cloudhous-property-hero-content h1 {
	font-family: var(--gutenverse-font-family-feature, "Michroma");
	font-size: 42px;
	margin: 0 0 8px;
}
.cloudhous-property-body {
	max-width: 1200px;
	margin: 60px auto;
	padding: 0 24px;
	display: grid;
	grid-template-columns: 2fr 1fr;
	gap: 60px;
	align-items: start;
}
@media (max-width: 900px) {
	.cloudhous-property-body {
		grid-template-columns: 1fr;
	}
}
.cloudhous-property-price {
	font-family: var(--gutenverse-font-family-feature, "Michroma");
	font-size: 28px;
	color: #14233D;
	margin-bottom: 20px;
}
.cloudhous-property-desc {
	color: rgba(20, 35, 61, 0.75);
	line-height: 1.7;
	margin-bottom: 30px;
}
.cloudhous-property-specs {
	display: flex;
	flex-wrap: wrap;
	gap: 24px;
	padding: 24px 0;
	border-top: 1px solid rgba(20, 35, 61, 0.1);
	border-bottom: 1px solid rgba(20, 35, 61, 0.1);
	margin-bottom: 30px;
}
.cloudhous-property-specs span {
	color: #14233D;
	font-size: 15px;
}
.cloudhous-property-specs i {
	color: #3D7DCB;
	margin-right: 8px;
}
.cloudhous-property-features {
	list-style: none;
	padding: 0;
	margin: 0 0 30px;
}
.cloudhous-property-features li {
	padding: 10px 0;
	border-bottom: 1px solid rgba(20, 35, 61, 0.08);
	color: rgba(20, 35, 61, 0.8);
}
.cloudhous-property-gallery {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 16px;
}
.cloudhous-property-gallery img {
	width: 100%;
	height: 220px;
	object-fit: cover;
	border-radius: 12px;
}
.cloudhous-property-sidebar {
	position: sticky;
	top: 110px;
}
.cloudhous-property-inquiry {
	background: #F5F7FA;
	border-radius: 16px;
	padding: 30px;
}
.cloudhous-property-inquiry h3 {
	font-family: var(--gutenverse-font-family-feature, "Michroma");
	font-size: 18px;
	color: #14233D;
	margin: 0 0 20px;
}
.cloudhous-property-inquiry form {
	display: flex;
	flex-direction: column;
	gap: 14px;
}
.cloudhous-property-inquiry input,
.cloudhous-property-inquiry textarea {
	border: none;
	border-bottom: 1px solid rgba(20, 35, 61, 0.3);
	background: transparent;
	padding: 10px 4px;
	font-size: 15px;
	font-family: inherit;
	color: #14233D;
}
.cloudhous-property-inquiry input::placeholder,
.cloudhous-property-inquiry textarea::placeholder {
	color: rgba(20, 35, 61, 0.5);
}
.cloudhous-property-inquiry button {
	margin-top: 8px;
	background: #3D7DCB;
	color: #fff;
	border: none;
	border-radius: 30px;
	padding: 14px;
	font-size: 15px;
	font-weight: 600;
	cursor: pointer;
}
.cloudhous-property-inquiry button:hover {
	background: #2f65a8;
}
.cloudhous-inquiry-success {
	color: #1a7f37;
	background: rgba(26, 127, 55, 0.1);
	padding: 12px 16px;
	border-radius: 8px;
}
.cloudhous-inquiry-error {
	color: #b42318;
	background: rgba(180, 35, 24, 0.1);
	padding: 12px 16px;
	border-radius: 8px;
}
.cloudhous-property-other {
	max-width: 1200px;
	margin: 0 auto 80px;
	padding: 0 24px;
}
.cloudhous-property-other h2 {
	font-family: var(--gutenverse-font-family-feature, "Michroma");
	font-size: 28px;
	color: #14233D;
	margin-bottom: 24px;
}
