/**
 * PP Malaga - Banner Anuncios
 *
 * Two states for the homepage row:
 *   with banners -> 70% block + 30% banner column (widths set in Elementor)
 *   no banners   -> the loop slot is removed and the block spans the row
 *
 * The override below beats Elementor's own rule
 * (.elementor-17 .elementor-element.elementor-element-s125box, 0-3-0)
 * on specificity alone (0-3-1), so no !important is needed.
 */

body:not(.pp-has-banners) .pp-banners-slot {
	display: none;
}

body:not(.pp-has-banners) .elementor-element.pp-banners-sibling {
	--width: 100%;
}

/**
 * Card treatment (padding, border, radius) lives on the loop item container and
 * is set through Elementor's own container controls, not here, so it stays
 * editable in the builder. This file only carries what Elementor cannot express.
 *
 * Image sizing: Elementor wraps a linked image in an inline-block <a>, which
 * shrinks to the image's intrinsic width. The image's own width:100% then
 * resolves against that shrunken box, so the banner can never grow past its
 * uploaded size. A full-width block link breaks that circular sizing.
 */
.pp-banner-anuncio .pp-banner-anuncio__img a {
	display: block;
	width: 100%;
}

.pp-banner-anuncio .pp-banner-anuncio__img img {
	display: block;
	width: 100%;
	height: auto;
	/* The image widget can pin an explicit width (currently 250px), which wins on
	   specificity over the 100% above. Auto side margins keep the image centred
	   inside the padded card either way. */
	margin-inline: auto;
	transition: transform 0.3s ease;
}

/**
 * A slight lift of the image on hover, and nothing else.
 *
 * The card itself does not move: its frame, border and position in the column
 * stay exactly where they are, so the top-and-bottom alignment against the
 * block beside it is never disturbed. Only the artwork breathes.
 *
 * No shadow, deliberately - it was removed from these cards once already, and
 * again from the document tiles. The hover language on this site is movement
 * and border, never a drop shadow.
 *
 * The rule hangs off the link rather than the card so the area that reacts is
 * exactly the area that can be clicked.
 *
 * The card carries no padding: the image reaches its border, so a 4% scale
 * would spill past the rounded corners. The clip below contains it.
 */
.pp-banner-anuncio .pp-banner-anuncio__img a:hover img,
.pp-banner-anuncio .pp-banner-anuncio__img a:focus-visible img {
	transform: scale(1.04);
}

@media (prefers-reduced-motion: reduce) {
	.pp-banner-anuncio .pp-banner-anuncio__img img {
		transition: none;
	}

	.pp-banner-anuncio .pp-banner-anuncio__img a:hover img,
	.pp-banner-anuncio .pp-banner-anuncio__img a:focus-visible img {
		transform: none;
	}
}

/**
 * Scope guard.
 *
 * The "Ultimas noticias" loop grid on the homepage carries custom CSS whose
 * rules are written without Elementor's `selector` prefix, so Elementor emits
 * `.elementor-loop-container` and `.e-loop-item` unscoped into post-17.css.
 * Those rules force display:flex / flex-direction:column / height:100% on every
 * loop grid on the page, which collapses this grid into a single column.
 *
 * Re-assert the grid behaviour inside our own slot only. Fixing the other
 * widget's custom CSS is a separate change; this keeps the two independent.
 */
.pp-banners-slot .elementor-loop-container {
	display: grid;
}

.pp-banners-slot .e-loop-item {
	display: block;
	height: auto;
}

/**
 * Fill the column, first banner at the top and last at the bottom.
 *
 * The slot already matches the height of the block beside it, but the loop grid
 * inside it is only as tall as its rows, so the banners bunched up and left a
 * gap under the last one. Nothing in the chain grows on its own: an Elementor
 * widget is sized by its content, so the widget, its container and the grid all
 * have to be told to take the space before align-content has any room to
 * distribute.
 *
 * With one banner space-between resolves to "top", which is the right answer
 * for a single card too.
 */
.pp-banners-slot .elementor-widget-loop-grid,
.pp-banners-slot .elementor-widget-loop-grid > .elementor-widget-container {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
}

.pp-banners-slot .elementor-loop-container {
	flex: 1 1 auto;
	align-content: space-between;
}

/**
 * Keep the zoom inside the frame.
 *
 * Written as Elementor's own --overflow custom property rather than a plain
 * `overflow: hidden`: .e-con declares `overflow: var(--overflow)`, so a flat
 * declaration ties on specificity and loses on source order, exactly as a flat
 * `padding` would. Setting the variable works with that mechanism instead of
 * against it.
 *
 * Clipping on the card and not on the link is deliberate: the radius lives on
 * the card and is set in Elementor, so the clip follows whatever radius the
 * builder holds. Hard-coding it on the link would drift the day someone changes
 * it there.
 */
.pp-banners-slot .pp-banner-anuncio {
	--overflow: hidden;
}

/**
 * Slider state.
 *
 * Only present once the JS has decided there is something to slide, so the
 * static column keeps its grid behaviour untouched whenever there are two
 * banners or fewer.
 *
 * The grid rules above have to be undone rather than avoided: Swiper needs the
 * loop container to be a flex column it can translate, and `align-content:
 * space-between` on a grid would fight the transform.
 */
.pp-banners-slot--slider .elementor-loop-container {
	display: flex;
	align-content: normal;
}

/*
 * The axis follows Swiper's own state class instead of being pinned here, so
 * the breakpoint that turns the carousel horizontal does not have to fight a
 * flex-direction written in stone.
 */
.pp-banners-slot--slider .swiper-vertical .elementor-loop-container {
	flex-direction: column;
}

.pp-banners-slot--slider .swiper-horizontal .elementor-loop-container {
	flex-direction: row;
}

/**
 * Exactly one thing may space the slides, and it has to be Swiper.
 *
 * The loop grid carries its own 16px row gap. Swiper adds spaceBetween as a
 * margin on each slide, so the two stacked: slides sat 220px apart while Swiper
 * translated by the 204px it believed in, and that 16px error pushed the second
 * banner out of view. Swiper cannot see a flex gap, so the gap is the one that
 * has to go.
 *
 * The doubled class is not decoration. Elementor declares this as
 * `.elementor-widget-loop-grid .elementor-grid { row-gap: var(--grid-row-gap) }`
 * at 0-2-0 - the same weight as a two-class selector of ours - and its
 * stylesheet loads later, so an equal-weight rule here silently loses. Adding
 * the second class on the same element makes it 0-3-0 and the outcome stops
 * depending on load order.
 */
.pp-banners-slot--slider .elementor-loop-container.elementor-grid {
	row-gap: 0;
	/*
	 * Both axes, not just the one in use. Zeroing only row-gap fixed the
	 * vertical carousel and left the identical bug waiting on the horizontal
	 * one: slides sat 375px apart while Swiper translated by the 359px it
	 * believed in, and the 16px error accumulated into a visible drift.
	 */
	column-gap: 0;
}

/**
 * The slider is taken out of flow, and that is the whole trick.
 *
 * Looping duplicates the slides. Stacked in normal flow they made the row
 * 4057px tall - and the row's height is exactly what should bound the slider,
 * so letting the slider feed it back is circular. Absolute positioning means
 * the slides no longer contribute any height: the host keeps taking its height
 * from the row, which the block beside it sets, and the slider fills whatever
 * that turns out to be.
 *
 * The floor is there for the opposite case: if the block beside it were ever
 * short, the slider must not collapse to nothing.
 */
/*
 * The height is set from JS, measured from the real proportion of the banners
 * (see claimHeight). A number written here could only ever be a guess about
 * images it has never seen, and that guess is what let the cards overflow their
 * slides once the control strip took its band.
 */
.pp-banners-slot--slider .elementor-widget-loop-grid > .elementor-widget-container {
	position: relative;
}

.pp-banners-slot--slider .pp-banners-swiper {
	position: absolute;
	/* Bottom inset leaves the control strip its band. Both are out of flow, so
	   neither feeds height back into the row. */
	/* The strip's band plus a gap, so the controls are not hard against the
	   last banner. Both values are mirrored in the JS that claims the height. */
	inset: 0 0 calc(var(--pp-banners-ui-height, 30px) + var(--pp-banners-ui-gap, 12px)) 0;
	overflow: hidden;
}

.pp-banners-slot--slider .swiper-slide {
	height: auto;
}



/**
 * Control strip: a time line and two arrows.
 *
 * Its height is the slack that used to misalign the two columns. The block on
 * the left stands 392px tall on its own and two banner cards plus their gap
 * come to 362, so the 30px difference was showing as a column that did not
 * line up. Spending exactly that difference on the controls makes each slide
 * (392 - 16 - 30) / 2 = 173px, which is the card's natural height: the columns
 * end flush with nothing stretched and nothing cropped.
 *
 * Out of flow like the slider, so it cannot feed height back into the row.
 */
.pp-banners-ui {
	position: absolute;
	right: 0;
	bottom: 0;
	left: 0;
	display: flex;
	align-items: center;
	gap: 12px;
	height: var(--pp-banners-ui-height, 30px);
}

/**
 * The time line is ambient, not a control: it answers "how long until the next
 * one" for anyone who happens to look, and should not compete with the arrows
 * beside it. So the track is barely a tint rather than a grey rule, and the
 * fill uses azul2 - the palette's lighter blue - instead of the azulpp the
 * arrows claim.
 */
.pp-banners-ui__time {
	position: relative;
	flex: 1 1 auto;
	height: 2px;
	overflow: hidden;
	border-radius: 2px;
	background-color: rgba(17, 34, 51, 0.08);
}

.pp-banners-ui__bar {
	position: absolute;
	inset: 0 auto 0 0;
	width: 0;
	/* The track clips its own left end round; this rounds the end that grows,
	   which is the one actually moving. At 2px tall the radius makes a pill. */
	border-radius: 2px;
	background-color: var(--e-global-color-azul2, #5896ce);
}

/**
 * The bar is animated rather than transitioned so it can be paused mid-flight
 * and pick up where it left off. A transition would have to be restarted, which
 * quietly hands the slide a fresh full delay every time the pointer crosses it.
 */
.pp-banners-ui__bar.is-running {
	animation-name: pp-banners-time;
	animation-timing-function: linear;
	animation-fill-mode: forwards;
}

.pp-banners-ui__bar.is-paused {
	animation-play-state: paused;
}

@keyframes pp-banners-time {
	from { width: 0; }
	to { width: 100%; }
}

.pp-banners-ui__nav {
	display: flex;
	flex: 0 0 auto;
	gap: 4px;
}

/**
 * The arrows follow this site's own button idiom rather than inventing one.
 *
 * Every button on these pages - the hero pair, the newsletter and join buttons -
 * is a square with a 2px border that inverts on hover: the colour and the
 * background swap places. Circles with a thin grey ring belonged to no part of
 * the design, which is why they read as foreign.
 *
 * 26px keeps the target above the 24px minimum while still clearing the 30px
 * strip.
 */
/*
 * The selector is heavier than it looks like it needs to be, and the border is
 * written as longhands rather than the shorthand. Both are deliberate.
 *
 * The theme's reset styles every bare button:
 *
 *   [type=button], [type=submit], button {
 *     border: 1px solid #c36; border-radius: 3px; padding: .5rem 1rem;
 *   }
 *
 * That is 0-0-1 and a single class already outranks it, yet it was still the
 * rule painting these arrows in the browser. Rather than assert the cascade
 * should have worked, this names the element as well as two classes (0-2-1) so
 * the outcome cannot depend on whatever was beating it.
 *
 * The longhands matter for the same reason: a shorthand carrying var() is
 * dropped whole if the custom property ever resolves empty, which would hand
 * the border straight back to the reset. Split up, only the colour could fail.
 */
.pp-banners-ui button.pp-banners-ui__arrow {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	min-width: 0;
	padding: 0;
	border-width: 1px;
	border-style: solid;
	border-color: var(--e-global-color-gris300, #d4d5d5);
	border-radius: 50%;
	background-color: transparent;
	/*
	 * Grey at rest, blue on contact. The controls sit beside the banners, not
	 * in front of them: at rest they should be findable without asking for
	 * attention, and the brand colour is what rewards reaching for one.
	 * gris300 alone would be too faint for the chevron itself, so that takes a
	 * muted ink instead of the border's grey.
	 */
	color: rgba(16, 42, 67, 0.5);
	font-size: inherit;
	line-height: 1;
	cursor: pointer;
	transition: border-color 0.2s ease, color 0.2s ease;
}

.pp-banners-ui button.pp-banners-ui__arrow svg {
	width: 12px;
	height: 12px;
}

/*
 * Hover stays in the greys: the same ink and border, simply a little firmer.
 * Enough to answer the pointer, not enough to pull the eye away from the
 * banners, which are the thing worth clicking here.
 */
.pp-banners-ui button.pp-banners-ui__arrow:hover,
.pp-banners-ui button.pp-banners-ui__arrow:focus-visible {
	border-color: rgba(16, 42, 67, 0.28);
	color: rgba(16, 42, 67, 0.75);
}

.pp-banners-ui button.pp-banners-ui__arrow:focus-visible {
	outline: 2px solid var(--e-global-color-azulbrillante, #278bff);
	outline-offset: 2px;
}

/* Swiper marks an arrow disabled at the ends; looping means that never happens,
   but the state is honoured in case looping is ever turned off. */
.pp-banners-ui button.pp-banners-ui__arrow.swiper-button-disabled {
	opacity: 0.35;
	cursor: default;
}

@media (prefers-reduced-motion: reduce) {
	.pp-banners-ui button.pp-banners-ui__arrow {
		transition: none;
	}
}

/**
 * Narrow screens: the carousel lies down and rejoins the flow.
 *
 * With the columns stacked there is no block beside this one to lend it a
 * height, which is why the vertical pair had to lean on a fixed floor and the
 * cards ended up overflowing their slides. Running horizontally, the slides sit
 * side by side and the tallest one gives the wrapper its height - so the slider
 * can go back into normal flow, where it simply measures itself.
 *
 * That also means nothing here is absolutely positioned, so the strip is laid
 * out after the slider rather than pinned over it.
 */
@media (max-width: 767px) {
	.pp-banners-slot--slider .elementor-widget-loop-grid > .elementor-widget-container {
		position: static;
	}

	.pp-banners-slot--slider .pp-banners-swiper {
		position: static;
		inset: auto;
		/*
		 * min-width: 0 is the point of these three.
		 *
		 * Out of absolute positioning the slider becomes an ordinary flex item,
		 * and a flex item defaults to min-width: auto - it refuses to shrink
		 * below its content. Its content is a row of every slide and clone, so
		 * it claimed 274799px and took the page's horizontal scroll with it.
		 * The overflow: hidden it already carries only clips what is inside;
		 * it cannot stop the box itself from growing.
		 */
		width: 100%;
		max-width: 100%;
		min-width: 0;
	}

	.pp-banners-slot--slider .elementor-widget-loop-grid,
	.pp-banners-slot--slider .elementor-widget-loop-grid > .elementor-widget-container {
		min-width: 0;
	}

	.pp-banners-slot--slider .pp-banners-ui {
		position: static;
		margin-top: var(--pp-banners-ui-gap, 12px);
	}

	/*
	 * The chevrons are drawn pointing up and down for the vertical carousel.
	 * Lying down, that reads as the wrong axis entirely, so they turn with it:
	 * -90deg takes up to left and down to right.
	 */
	.pp-banners-ui button.pp-banners-ui__arrow svg {
		transform: rotate(-90deg);
	}
}