﻿/**
 * Popular Tours widget.
 *
 * Colour and type resolve through component tokens declared on `.goxom-pt`,
 * each pointing at a theme global first (--color-primary, --color-black,
 * --font-title â€¦) with a literal fallback for the Elementor editor, where the
 * theme stylesheet is not always loaded.
 *
 * Cards are never left invisible: the "hide first" rule is scoped to
 * `.goxom-pt--js`, which the JS adds only once it knows GSAP is available, and
 * the GSAP-less path gets `.goxom-pt--css` keyframes instead.
 */

.goxom-pt {
	/* Brand */
	--pt-primary: var(--color-primary, #1273C4);
	--pt-primary-dark: var(--color-primary-dark, #0B5596);

	/* Ink */
	--pt-title: var(--color-black, #0C2338);
	--pt-body: var(--color-body, #5A7387);
	--pt-white: var(--color-white, #ffffff);

	/* Surface. The card itself is deliberately transparent: its body is flush
	   with the artwork (no side or bottom padding), so a painted card surface
	   would box the title and the button against their own edges. The `card_bg`
	   control still sets one for anyone who also gives the body padding. */
	--pt-card: transparent;
	--pt-tint: var(--color-tint, #F0F6FC);
	--pt-line: var(--color-border, #D5E3EF);

	/* Type */
	--pt-font-title: var(--font-title, inherit);
	--pt-font-body: var(--font-body, inherit);

	/* Shape */
	--pt-radius: 14px;
	--pt-ease: cubic-bezier(.22, .61, .36, 1);

	position: relative;
	padding: 100px 20px;
	font-family: var(--pt-font-body);
}

.goxom-pt__inner {
	position: relative;
	max-width: 1320px;
	margin-inline: auto;
}

/* ================================================================== heading */

.goxom-pt__head {
	margin-bottom: 52px;
	text-align: center;
}

.goxom-pt__subtitle {
	display: block;
	margin-bottom: 12px;
	font-family: var(--pt-font-title);
	font-size: 15px;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--pt-primary);
}

.goxom-pt__title {
	margin: 0;
	font-family: var(--pt-font-title);
	font-size: clamp(30px, 4vw, 52px);
	line-height: 1.14;
	font-weight: 700;
	color: var(--pt-title);
}

/* Word masking for the default title animation â€” the JS injects these, so with
   no JS the heading stays plain text. */
.goxom-pt__title .goxom-pt__w {
	display: inline-block;
	overflow: hidden;
	vertical-align: top;
}

.goxom-pt__title .goxom-pt__w > span,
.goxom-pt__title .goxom-pt__char {
	display: inline-block;
	will-change: transform, opacity;
}

/* ===================================================================== grid */

.goxom-pt__grid {
	--goxom-pt-cols: 3;
	display: grid;
	grid-template-columns: repeat(var(--goxom-pt-cols), minmax(0, 1fr));
	gap: 30px;
}

/* ==================================================================== cards */

/* A flex column so the body can stretch: with titles of different lengths the
   footer row would otherwise sit at a different height on every card. */
.goxom-pt__card {
	position: relative;
	display: flex;
	flex-direction: column;
	border-radius: var(--pt-radius);
	background-color: var(--pt-card);
	transition: transform .45s var(--pt-ease), box-shadow .45s var(--pt-ease);
}

/* The hover lift moves the card's two children rather than the card, and the
   shadow lands on the artwork rather than around the whole card. Both for the
   same reason, from opposite ends:
   - the reveal tween has to leave `opacity: 1` inline on the card, so it leaves
     an identity `transform` there too, and an inline style outranks anything
     the stylesheet says about `:hover` — a lift on `.goxom-pt__card` is simply
     never applied once the cards have revealed;
   - the body is flush with the photo by design (no side or bottom padding), so
     a shadow drawn around the card puts a hard edge hard against the title,
     the price and the button. The photo is the one part of a card that has a
     surface of its own, so it is the one part that can cast a shadow.
   Transforming both children is visually identical to transforming the card,
   and neither of them is a tween target. */
.goxom-pt--lift .goxom-pt__card:hover .goxom-pt__media,
.goxom-pt--lift .goxom-pt__card:hover .goxom-pt__body,
.goxom-pt--lift .goxom-pt__card:focus-within .goxom-pt__media,
.goxom-pt--lift .goxom-pt__card:focus-within .goxom-pt__body {
	transform: translateY(-8px);
}

.goxom-pt--lift .goxom-pt__card:hover .goxom-pt__media,
.goxom-pt--lift .goxom-pt__card:focus-within .goxom-pt__media {
	box-shadow: 0 22px 40px -24px color-mix(in srgb, var(--pt-title) 50%, transparent);
}

/* ---------------------------------------------------------------- artwork */

.goxom-pt__media {
	position: relative;
	overflow: hidden;
	aspect-ratio: 1.32;
	border-radius: var(--pt-radius);
	background-color: var(--pt-tint);
	transition: transform .45s var(--pt-ease), box-shadow .45s var(--pt-ease);
}

.goxom-pt__media-link {
	display: block;
	width: 100%;
	height: 100%;
}

/* The parent class is in this selector to win a specificity fight, not for
   readability: Elementor ships `.elementor img { height: auto }` at (0,1,1),
   which outranks a lone `.goxom-pt__img` at (0,1,0). And `height: auto` is not
   harmless here â€” an absolutely positioned *replaced* element resolves it to
   the image's intrinsic height and ignores `bottom`, so the photo renders at
   its natural size and leaves a strip of card showing underneath. */
.goxom-pt__media .goxom-pt__img {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform .7s var(--pt-ease);
}

.goxom-pt__card:hover .goxom-pt__img,
.goxom-pt__card:focus-within .goxom-pt__img {
	transform: scale(1.06);
}

.goxom-pt__img--empty {
	background-image: linear-gradient(
		135deg,
		color-mix(in srgb, var(--pt-primary) 18%, transparent),
		color-mix(in srgb, var(--pt-title) 12%, transparent)
	);
}

.goxom-pt__badges {
	position: absolute;
	top: 14px;
	left: 14px;
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.goxom-pt__badge {
	display: inline-flex;
	align-items: center;
	padding: 6px 12px;
	border-radius: 999px;
	background-color: var(--pt-primary);
	color: var(--pt-white);
	font-size: 12px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: .02em;
	white-space: nowrap;
}

/* ------------------------------------------------------------------- body */

/* Two columns: the tour and its duration on the left, what it costs and how to
   book it on the right â€” which is the order the eye wants them in. */
.goxom-pt__body {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 16px;
	flex: 1 1 auto;
	/* Flush with the artwork's edges, so the title lines up with the photo
	   rather than being inset from it. The padding control is there for anyone
	   who gives the card a background of its own. */
	padding: 20px 0 0;
	transition: transform .45s var(--pt-ease);
}

.goxom-pt__main {
	min-width: 0;
	flex: 1 1 auto;
}

.goxom-pt__side {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 10px;
	flex: 0 0 auto;
}

.goxom-pt__name {
	margin: 0 0 10px;
	font-family: var(--pt-font-title);
	font-size: 20px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--pt-title);
}

/* No underline on hover, in either form. A background-gradient wipe paints
   across the whole inline box and draws a full-width rule the moment a title
   wraps; a text-decoration follows the glyphs correctly but still reads as a
   stray line under a two-line title. The colour shift alone is the hover cue â€”
   the card lift and the image zoom already carry it. */
.goxom-pt__name a {
	color: inherit;
	text-decoration: none;
	transition: color .3s ease;
}

.goxom-pt__card:hover .goxom-pt__name a,
.goxom-pt__name a:focus-visible {
	color: var(--pt-primary);
}

.goxom-pt__name a:focus-visible {
	outline: 2px solid var(--pt-primary);
	outline-offset: 3px;
	border-radius: 3px;
}

.goxom-pt__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px 16px;
	margin: 0;
	font-size: 15px;
	line-height: 1.4;
	color: var(--pt-body);
}

.goxom-pt__meta-item {
	display: inline-flex;
	align-items: center;
	gap: 7px;
}

/* Fixed box, and flex-shrink pinned to 0: in a wrapping flex row a shrinkable
   icon gets squeezed narrower than its viewBox and the circle draws as an arc. */
.goxom-pt__meta .goxom-pt__meta-item svg {
	display: block;
	flex: 0 0 17px;
	width: 17px;
	height: 17px;
	min-width: 17px;
	color: var(--pt-body);
	opacity: .85;
}

/* ------------------------------------------------------------------ price */

.goxom-pt__price {
	display: flex;
	align-items: baseline;
	gap: 8px;
	margin: 0;
	font-family: var(--pt-font-title);
	font-size: 20px;
	font-weight: 700;
	line-height: 1.2;
	color: var(--pt-title);
	white-space: nowrap;
}

.goxom-pt__was {
	font-size: .72em;
	font-weight: 500;
	text-decoration: line-through;
	color: var(--pt-body);
	opacity: .75;
}

/* ----------------------------------------------------------------- button */

.goxom-pt__btn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	padding: 9px 20px;
	border: 1.4px solid var(--pt-primary);
	border-radius: 999px;
	background-color: transparent;
	color: var(--pt-primary);
	font-family: var(--pt-font-body);
	font-size: 14px;
	font-weight: 700;
	line-height: 1.2;
	text-decoration: none;
	white-space: nowrap;
	transition: color .35s var(--pt-ease), border-color .35s var(--pt-ease),
	            background-color .35s var(--pt-ease);
}

.goxom-pt__btn > span {
	position: relative;
	z-index: 1;
}

/* The fill wipes up from the bottom instead of the whole button changing
   colour at once â€” same cost, and it reads as a deliberate response. */
.goxom-pt__btn::before {
	content: "";
	position: absolute;
	inset: 0;
	background-color: var(--pt-primary);
	transform: scaleY(0);
	transform-origin: 50% 100%;
	transition: transform .4s var(--pt-ease);
}

.goxom-pt__btn:hover,
.goxom-pt__btn:focus-visible {
	color: var(--pt-white);
	border-color: var(--pt-primary);
}

.goxom-pt__btn:hover::before,
.goxom-pt__btn:focus-visible::before {
	transform: scaleY(1);
}

.goxom-pt__btn:focus-visible {
	outline: 3px solid color-mix(in srgb, var(--pt-primary) 40%, transparent);
	outline-offset: 2px;
}

/* ================================================================== notices */

.goxom-pt__notice {
	padding: 22px;
	border: 1px dashed color-mix(in srgb, var(--pt-title) 35%, transparent);
	border-radius: 12px;
	text-align: center;
	color: var(--pt-title);
	background-color: color-mix(in srgb, var(--pt-primary) 7%, transparent);
}

/* ================================================================== reveals */

/* Only hide cards once JS has confirmed it will animate them. */
.goxom-pt--js[data-reveal="rise"] .goxom-pt__card,
.goxom-pt--js[data-reveal="wipe"] .goxom-pt__card,
.goxom-pt--js[data-reveal="scale"] .goxom-pt__card,
.goxom-pt--js[data-reveal="fade"] .goxom-pt__card {
	opacity: 0;
}

/* GSAP-less fallback: the same reveals as keyframes, staggered by nth-child so
   the grid still arrives in a wave. */
.goxom-pt--css[data-reveal] .goxom-pt__card {
	animation: goxom-pt-rise .7s var(--pt-ease) both;
}

.goxom-pt--css[data-reveal="scale"] .goxom-pt__card { animation-name: goxom-pt-scale; }
.goxom-pt--css[data-reveal="fade"] .goxom-pt__card  { animation-name: goxom-pt-fade; }
.goxom-pt--css[data-reveal="wipe"] .goxom-pt__card  { animation-name: goxom-pt-wipe; }

.goxom-pt--css[data-reveal=""] .goxom-pt__card {
	animation: none;
	opacity: 1;
}

.goxom-pt--css .goxom-pt__card:nth-child(2)   { animation-delay: .08s; }
.goxom-pt--css .goxom-pt__card:nth-child(3)   { animation-delay: .16s; }
.goxom-pt--css .goxom-pt__card:nth-child(4)   { animation-delay: .24s; }
.goxom-pt--css .goxom-pt__card:nth-child(5)   { animation-delay: .32s; }
.goxom-pt--css .goxom-pt__card:nth-child(6)   { animation-delay: .40s; }
.goxom-pt--css .goxom-pt__card:nth-child(n+7) { animation-delay: .48s; }

@keyframes goxom-pt-rise {
	from { opacity: 0; transform: translateY(38px); }
	to   { opacity: 1; transform: none; }
}

@keyframes goxom-pt-scale {
	from { opacity: 0; transform: scale(.9); }
	to   { opacity: 1; transform: none; }
}

@keyframes goxom-pt-fade {
	from { opacity: 0; }
	to   { opacity: 1; }
}

@keyframes goxom-pt-wipe {
	from { opacity: 0; clip-path: inset(0 0 100% 0); }
	to   { opacity: 1; clip-path: inset(0 0 0 0); }
}

.goxom-pt--css[data-title-anim] .goxom-pt__title {
	animation: goxom-pt-rise .8s var(--pt-ease) both;
}

/* =============================================================== breakpoints */

@media (max-width: 1024px) {
	.goxom-pt__grid {
		--goxom-pt-cols: 2;
	}
}

@media (max-width: 767px) {
	.goxom-pt {
		padding: 64px 16px;
	}

	.goxom-pt__grid {
		--goxom-pt-cols: 1;
		gap: 22px;
	}

	/* Side by side, the price and button squeeze the title into two or three
	   lines on a phone. Stacking gives the title the full width and puts the
	   button under it, where a thumb is anyway. */
	.goxom-pt__body {
		flex-direction: column;
		align-items: stretch;
		gap: 14px;
	}

	.goxom-pt__side {
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
	}
}

/* color-mix is recent enough that a couple of shipping browsers still miss it;
   without these the shadow and the empty-image tint render transparent. */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
	.goxom-pt--lift .goxom-pt__card:hover .goxom-pt__media {
		box-shadow: 0 26px 44px -24px rgba(13, 27, 107, .45);
	}

	.goxom-pt__img--empty {
		background-image: linear-gradient(135deg, rgba(18, 115, 196, .18), rgba(13, 27, 107, .12));
	}

	.goxom-pt__notice {
		border-color: rgba(13, 27, 107, .35);
		background-color: rgba(18, 115, 196, .07);
	}
}

@media (prefers-reduced-motion: reduce) {
	.goxom-pt__card,
	.goxom-pt__media,
	.goxom-pt__body,
	.goxom-pt__img,
	.goxom-pt__btn,
	.goxom-pt__btn::before,
	.goxom-pt__name a {
		transition: none !important;
	}

	.goxom-pt--css[data-reveal] .goxom-pt__card,
	.goxom-pt--css[data-title-anim] .goxom-pt__title,
	.goxom-pt--js[data-reveal] .goxom-pt__card {
		animation: none !important;
		opacity: 1 !important;
		transform: none !important;
		clip-path: none !important;
	}
}
