/*
Version: 1.18.6
Version date: 30-09-2026

Asty Booking — front end.

Scoped entirely to `.astyb-*`. Nothing here may style a host selector: Villagio
and Hotel Booking both self-update, and a rule of ours that reaches into
`.mphb-*` would either be overwritten or start fighting a stylesheet we do not
control.

Colours are deliberately derived from `currentColor` and neutral greys rather
than named. The theme owns the palette; this owns the layout.

⚠ House rule, stated once for the front-end scope, exactly as
`property-editor.css` states it for the admin: `[hidden]` is a USER-AGENT rule
and loses to any author `display`. Anything rendered `hidden` that also carries
a class setting `display` needs the rule below. Add new cases to it rather than
writing a fourth per-selector patch.
*/

.astyb-prices [hidden],
.astyb-cta [hidden],
.astyb-request [hidden],
.astyb-loop-prices [hidden] {
	display: none;
}

/*
⚠⚠ House rule 2, and the same shape as the one above: THE THEME SPACES EVERY
LIST IN THE DOCUMENT.

Villagio ships TWO of them, and the second is why this rule is doubled:

    ul li + li, ol li + li { margin-top: 0.6875em }   (0,0,3)
    .widget ul li + li     { margin-top: 1.5em }      (0,1,3)

Sensible typography for prose, wrong for a list we are using as a control. Both
skip the FIRST item, so the symptom is never "everything is spaced out", which
would be obvious. It is "the first item sits higher than the others", which reads
as a broken layout of ours.

⚠⚠ **The class is repeated deliberately** — `.astyb-badges.astyb-badges` is
(0,2,1), which beats the widget rule's (0,1,3) on class count. A single class is
(0,1,1) and **loses inside a widget while winning in the content column**, so the
same component looks right on a page and broken in a sidebar. That is precisely
the bug this comment exists to stop being rediscovered: the first fix here was a
single class, it passed on the page, and Panos found it in the sidebar.

★ ADD A NEW LIST OF OURS TO THIS SELECTOR, doubled — never a private patch.

⚠⚠ **IT RESETS `margin` ONLY, AND THAT IS DELIBERATE — 18-08-2026.** It used to
reset `padding` too, and that was over-reach with a real cost: the doubled class
is (0,2,1), so it beat `.astyb-badge { padding: .2em .7em }` at (0,1,0) and
**flattened every plan badge into bare text** — the rounded pill had no room
inside it. Panos found it and read the two rules against each other.

★ The theme imposes `margin-top` on `li + li` and **nothing else**: checked
Villagio's stylesheet and the `so-css` custom CSS, and neither sets padding on a
bare `li` (nor does any user agent — the indent lives on the `ul`, which each of
our lists already zeroes for itself). So there was nothing for the padding half
to defend against, and its only effect was to silently eat any padding a
component of ours wanted on its own list items.

⚠ **Never widen this reset to a property the theme does not actually set.** A
reset is a counter-measure, not a tidy-up: every property it takes is one a
component below can no longer use without fighting a specificity it cannot see.
*/
.astyb-search__modes.astyb-search__modes > li,
.astyb-badges.astyb-badges > li,
.astyb-tiers.astyb-tiers > li,
.astyb-crumbs-list.astyb-crumbs-list > li,
.astyb-facts.astyb-facts > li,
.astyb-card__facts--icons.astyb-card__facts--icons > li,
.astyb-amenity-grid.astyb-amenity-grid > li,
.astyb-feature-list.astyb-feature-list > li,
.astyb-amenities.astyb-amenities > li {
	margin: 0;
}

/*
⚠⚠ House rule 3, found 16-08-2026 and the SAME SHAPE AS RULES 1 AND 2 — it is
the paragraph version of them, and it had been missed:

    p          { margin: 0 0 1.5em }        (0,0,1)
    .widget p  { margin-bottom: 1.78571em } (0,1,1)

★ Panos found it: the filter column is Villagio's own `sidebar-1` widget, so
every `<p>` of ours in that column — each `.astyb-field`, and the submit row —
was carrying 1.78571em of bottom margin that a single class **cannot** remove.
`.astyb-field { margin: 0 }` is (0,1,0) and **loses to (0,1,1)**, so the form
looked right in the content column and loose and uneven in the sidebar. Exactly
the trap the comment above describes, one element type over.

⚠ There is no shared reset here, because unlike a list item each of these
paragraphs wants a *different* margin. The class is therefore repeated **on the
rule that sets it**, wherever one of our paragraphs can land in a widget. Both
are marked with a back-reference to this comment.

★ ADD ANY NEW `<p>` OF OURS THE SAME WAY — doubled, at the point it is styled.
*/

/* ---------------------------------------------------------------------------
   Plan badges
   ------------------------------------------------------------------------ */

.astyb-badges {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4em;
	margin: 0 0 1em;
	padding: 0;
	list-style: none;
}

.astyb-badge {
	display: inline-block;
	padding: 0.2em 0.7em;
	border: 1px solid currentColor;
	border-radius: 2em;
	font-size: 0.75em;
	line-height: 1.6;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	opacity: 0.8;
}

/* A sale is not a rental, and the badge is the first thing that says so. */
.astyb-badge--sale {
	border-style: dashed;
}

/* ★ 1.18.2 — the badges over a corner of a card's photograph (Layout → the
   Badges row, «Where the badges sit»). The Photograph section becomes the
   positioning frame; it has no offsets, so nothing else in it moves.
   ⚠ A light pill with dark text, opaque: a badge that is outline-only and
   80 % opaque disappears on a busy picture. The border stays, so a sale keeps
   its dashed edge. */
.astyb-card .astyb-section--image {
	position: relative;
}

/* One box per corner; everything set on that corner stacks inside it
   (badges, then location, then availability), so two lines on one corner sit
   one under the other rather than on top of each other. */
.astyb-card .astyb-card__over {
	position: absolute;
	z-index: 1;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.35em;
	max-width: calc(100% - 1.2em);
	pointer-events: none;
}

.astyb-card__over--tl { top: 0.6em; left: 0.6em; }
.astyb-card__over--tr { top: 0.6em; right: 0.6em; }
.astyb-card__over--bl { bottom: 0.6em; left: 0.6em; }
.astyb-card__over--br { bottom: 0.6em; right: 0.6em; }

.astyb-card .astyb-card__over--tr,
.astyb-card .astyb-card__over--br {
	align-items: flex-end;
}

.astyb-card__over--tr .astyb-badges,
.astyb-card__over--br .astyb-badges {
	justify-content: flex-end;
}

.astyb-card__over .astyb-badges.astyb-badges {
	margin: 0;
}

.astyb-card__over .astyb-badge {
	background: rgba(255, 255, 255, 0.92);
	color: #1d2327;
	opacity: 1;
}

/* The location and availability lines, as pills. Two classes, so a sidebar's
   `.widget p` margin (0,1,1) cannot reach them — house rule 3. */
.astyb-card .astyb-card__over .astyb-card__location,
.astyb-card .astyb-card__over .astyb-card__available {
	display: inline-block;
	margin: 0;
	padding: 0.2em 0.7em;
	border-radius: 2em;
	background: rgba(255, 255, 255, 0.92);
	color: #1d2327;
	font-size: 0.8em;
	line-height: 1.5;
	opacity: 1;
}

/* ---------------------------------------------------------------------------
   The price block — single property
   ------------------------------------------------------------------------ */

.astyb-prices {
	display: flex;
	flex-wrap: wrap;
	gap: 1.5em;
	margin: 0 0 1.5em;
}

.astyb-offer {
	flex: 1 1 14em;
	min-width: 0;
	padding: 1em 1.2em;
	border: 1px solid rgba(0, 0, 0, 0.12);
	border-radius: 4px;
}

/* Class doubled (1.18.4) — a heading; see `.astyb-card__title`. */
.astyb-offer__label.astyb-offer__label {
	margin: 0 0 0.3em;
	font-size: 0.8em;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	opacity: 0.7;
}

.astyb-offer__headline {
	margin: 0;
	font-size: 1.5em;
	line-height: 1.3;
}

.astyb-offer__from,
.astyb-offer__period {
	font-size: 0.6em;
	font-weight: 400;
	opacity: 0.7;
}

.astyb-offer__length {
	margin: 0.6em 0 0;
	font-size: 0.8em;
	opacity: 0.7;
}

/* ---------------------------------------------------------------------------
   The length-of-stay tiers

   A native <details>, so the disclosure needs no script and cannot fall into
   the `[hidden]` trap above.
   ------------------------------------------------------------------------ */

.astyb-offer__tiers {
	margin: 0.7em 0 0;
	font-size: 0.85em;
}

.astyb-offer__tiers > summary {
	cursor: pointer;
	opacity: 0.75;
}

.astyb-tiers {
	margin: 0.5em 0 0;
	padding: 0;
	list-style: none;
}

.astyb-tier {
	display: flex;
	justify-content: space-between;
	gap: 1em;
	padding: 0.25em 0;
	border-bottom: 1px solid rgba(0, 0, 0, 0.07);
}

.astyb-tier:last-child {
	border-bottom: 0;
}

.astyb-tier__range {
	opacity: 0.75;
}

.astyb-tier__price {
	white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   The price on an archive card
   ------------------------------------------------------------------------ */

.astyb-loop-prices {
	margin: 0 0 0.8em;
}

.astyb-loop-price {
	display: flex;
	justify-content: space-between;
	gap: 0.8em;
	font-size: 0.95em;
}

/* ⚠ 1.18.3 — doubled, house rule 3: a card in a sidebar sits inside `.widget`,
   whose `p { margin-bottom: 1.78em }` (0,1,1) beat the single class and put a
   24px gap under the price in «We recommend». */
.astyb-loop-price.astyb-loop-price {
	margin: 0 0 0.2em;
}

.astyb-loop-price__label {
	opacity: 0.7;
}

/* ★ `margin-left: auto` keeps the price on the right when a card drops the
   plan name beside it (1.18.0) — `space-between` alone would pull a lone
   price to the left. */
.astyb-loop-price__value {
	margin-left: auto;
	white-space: nowrap;
	font-weight: 600;
}

/* The «Book» button standing where the plan name was. */
.astyb-loop-price--action {
	align-items: center;
}

/* ---------------------------------------------------------------------------
   The call to action
   ------------------------------------------------------------------------ */

.astyb-cta {
	margin: 1.5em 0;
}

.astyb-cta__actions {
	margin: 0;
}

/* ---------------------------------------------------------------------------
   The search form
   ------------------------------------------------------------------------ */

/*
 * ⚠ The search form is ONE component that lives at two very different widths:
 * the page content column, and a 283px sidebar widget — where the four tabs need
 * 361px of natural width and wrapped onto three ragged rows.
 *
 * ★ That is a CONTAINER query, not a media query, and the distinction is the
 * whole point: the **viewport is identical** in both cases. A `@media` rule
 * keyed to screen width could not tell the page form from the sidebar form, so
 * it would have to shrink both or neither.
 */
.astyb-search {
	container-type: inline-size;
	container-name: astyb-search;
	margin: 0 0 2em;
}

/*
 * Underline tabs rather than boxed ones.
 *
 * ⚠ The boxed version — three borders and rounded top corners, sitting on the
 * container's line — has to fake the join by painting over that line with the
 * panel's own background. That means hard-coding a background colour, and this
 * stylesheet deliberately names no colours: it borrows the theme's through
 * `currentColor` so it cannot fight a palette it does not control. A box whose
 * background guessed wrong would look broken on any theme but this one.
 *
 * An underline needs no such guess, cannot misalign, and says the same thing.
 */
.astyb-search__modes {
	display: flex;
	flex-wrap: wrap;
	align-items: stretch;
	gap: 0 0.4em;
	margin: 0;
	padding: 0;
	list-style: none;
	border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}

.astyb-search__mode > a {
	display: block;
	padding: 0.55em 0.9em;
	/* Transparent from the start, so becoming current changes a colour and
	   never a size — that is what keeps the row from shifting on click. */
	border-bottom: 2px solid transparent;
	text-decoration: none;
	opacity: 0.65;
}

.astyb-search__mode > a:hover,
.astyb-search__mode > a:focus {
	opacity: 1;
}

.astyb-search__mode.is-current > a {
	border-bottom-color: currentColor;
	font-weight: 600;
	opacity: 1;
}

/*
 * Narrow container — the sidebar widget.
 *
 * Four equal columns, so the tabs stay **one row of four** whatever the labels
 * say, with each label free to wrap onto a second line rather than pushing its
 * neighbour off the row. Centred, because a column narrower than its own text
 * reads better centred than ragged-left.
 *
 * ⚠ Sized in a plain length, not `em`: an `em` inside a container query resolves
 * against the container's own font-size, which the theme sets differently in a
 * widget than in the content column — so the breakpoint would move depending on
 * where the component was placed, which is exactly what it exists to stop.
 */
@container astyb-search (max-width: 400px) {

	.astyb-search__modes {
		display: grid;
		grid-template-columns: repeat(4, 1fr);
		gap: 0;
	}

	.astyb-search__mode > a {
		/* Fills the grid cell and centres in it, so a label that wraps to two
		   lines — «Medium term» at this width — does not leave the single-line
		   ones stranded against the top of the row. */
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		height: 100%;
		box-sizing: border-box;
		padding: 0.5em 0.2em;
		font-size: 0.78em;
		line-height: 1.25;
		text-align: center;
		hyphens: auto;
	}

	/* The count goes under the label rather than beside it — beside it, the
	   two together no longer fit a 71px column and the label wraps mid-word. */
	.astyb-search__mode-count {
		margin-left: 0;
	}

	.astyb-amenities {
		grid-template-columns: 1fr;
	}
}

/*
 * ⚠ Fallback for a browser without container queries: the tabs keep their
 * natural widths and wrap, which is what they did before this rule existed —
 * cramped, but every tab still present and still clickable. Nothing here is
 * load-bearing for the search working.
 */

.astyb-search__fields {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(11em, 1fr));
	gap: 0.8em 1em;
	margin: 1.2em 0 0;
}

/* ⚠ Doubled — house rule 3 at the top of this file. Seven of the twelve filters
   are a `<p>`, and in the sidebar widget a single class loses to `.widget p`. */
.astyb-field.astyb-field {
	margin: 0;
}

/*
The controls themselves, as the form ships.

★ Panos's two numbers, 16-08-2026: half an em of inner spacing and half an em of
space below. Villagio dresses every control on the site at `height: 3.125rem`
with `padding: 0.75em 1.25em 0.875em`, which is right for a contact form and far
too heavy for twelve filters stacked in a 283px column.

⚠ `height: auto` is load-bearing, not tidying: with the theme's fixed height in
place, changing the padding moves the text around inside a box that never
changes size, so the «inner spacing» control would look broken.

⚠⚠ This is (0,2,1) on purpose. Villagio reaches these controls with selectors
like `input[type="date"]` — also (0,1,1) — and **its stylesheet loads after
ours**, so anything weaker would lose on date and number inputs while winning on
selects: compact dropdowns beside tall date boxes, which reads as our bug.

⚠ The «field inside this section» controls generate a rule of the SAME
specificity, and win on source order — `wp_add_inline_style()` appends them to
this file's own handle, so they are always later. That is the same cascade
position every generated rule here relies on.
*/
.astyb-search .astyb-field :is(input, select, textarea) {
	height: auto;
	margin-bottom: 0.5em;
	padding: 0.5em;
}

.astyb-field > label {
	display: block;
	margin-bottom: 0.25em;
	font-size: 0.8em;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	opacity: 0.7;
}

.astyb-field > input,
.astyb-field > select {
	width: 100%;
	box-sizing: border-box;
}

/* ---------------------------------------------------------------------------
   A from/to pair, side by side in the space one control used to take.

   ⚠ `min-width: 0` on the inputs is load-bearing: a flex item's default
   `min-width: auto` refuses to shrink below the browser's intrinsic width for a
   number spinner, so without it the two boxes overflow their column instead of
   sharing it — visible only at narrow widths, which is where it matters most.
   ------------------------------------------------------------------------ */

.astyb-field__legend {
	display: block;
	margin-bottom: 0.25em;
	font-size: 0.8em;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	opacity: 0.7;
}

.astyb-range {
	display: flex;
	align-items: center;
	gap: 0.3em;
}

.astyb-range > input {
	flex: 1 1 0;
	min-width: 0;
	box-sizing: border-box;
}

.astyb-range__dash {
	flex: 0 0 auto;
	opacity: 0.45;
}

.astyb-search__mode-count {
	display: inline-block;
	margin-left: 0.35em;
	font-size: 0.78em;
	font-weight: 400;
	opacity: 0.6;
}

/* ⚠ Doubled — house rule 3 at the top of this file. This is a `<p>`, and in the
   sidebar widget the theme adds 1.78571em under it that a single class cannot
   remove — a gap below the Search button with nothing after it. */
.astyb-search__actions.astyb-search__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 1em;
	margin: 1.2em 0 0;
}

.astyb-search__reset {
	font-size: 0.9em;
	opacity: 0.75;
}

/* ---------------------------------------------------------------------------
   The compact search forms — [astyb_search_bar] and [astyb_search_mini]
   (1.18.0). One row, made to sit over a slider or a header image:

   - TRANSPARENT: the form paints no background, border or shadow of its own;
     the text colour is inherited, so on a dark picture set «Text colour» on
     the form's tab of the Layout screen. The fields keep the theme's own look
     (white boxes), which is what keeps them readable on any picture.
   - ONE ROW, wrapping on a narrow screen: every field grows from 9em, the
     button sits at the row's end, aligned to the bottoms of the boxes.
   ⚠ Every rule here is scoped to `.astyb-search--compact`; the full form and
     the sidebar widget are untouched.
   ------------------------------------------------------------------------ */

.astyb-search--compact {
	margin: 0;
	background: transparent;
}

.astyb-search--compact .astyb-search__form {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: 0.6em;
	margin: 0;
}

/* The grid of the full form becomes a row. */
.astyb-search--compact .astyb-search__fields {
	display: flex;
	flex: 1 1 24em;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: 0.6em;
	margin: 0;
}

.astyb-search--compact .astyb-search__fields > .astyb-section {
	flex: 1 1 9em;
	min-width: 0;
}

/* ⚠ Doubled — house rule 3: a `<p>` that may land in a widget. */
.astyb-search--compact .astyb-field.astyb-field {
	margin: 0;
}

.astyb-search--compact .astyb-field > label {
	color: inherit;
}

/* No gap under the boxes, so their bottoms and the button's line up.
   ⚠ The boxes get their OWN readable pair — white box, dark text. The form's
   text colour is meant for the labels over a picture (usually white), and
   inherited into the boxes it wrote white on white: seen in the browser, the
   first thing wrong. The «field» group on the Layout tab still overrides it. */
.astyb-search--compact .astyb-field :is(input, select) {
	width: 100%;
	margin-bottom: 0;
	box-sizing: border-box;
	background-color: #fff;
	color: #222;
}

.astyb-search--compact .astyb-field select:disabled {
	opacity: 0.75;
}

/* The tabs follow the form's text colour, not the theme's link green —
   two classes beat Villagio's `.entry-content a` (0,1,1). */
.astyb-search--compact .astyb-search__mode > a {
	color: inherit;
}

/* The button's section wrapper is the flex item, not the `<p>` inside it. */
.astyb-search--compact .astyb-search__form > .astyb-section {
	flex: 0 0 auto;
}

.astyb-search--compact .astyb-search__actions.astyb-search__actions {
	margin: 0;
}

.astyb-search--compact .astyb-search__modes {
	margin-bottom: 0.6em;
	border-bottom-color: currentColor;
}

/* ---------------------------------------------------------------------------
   Amenities — a collapsed disclosure, so 55 checkboxes cost no screen
   until they are wanted.
   ------------------------------------------------------------------------ */

.astyb-search__amenities {
	margin: 1em 0 0;
	font-size: 0.9em;
}

.astyb-search__amenities > summary {
	cursor: pointer;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	opacity: 0.7;
}

.astyb-search__amenities-count {
	display: inline-block;
	min-width: 1.6em;
	margin-left: 0.4em;
	padding: 0 0.4em;
	border-radius: 1em;
	background: rgba(0, 0, 0, 0.08);
	text-align: center;
}

.astyb-amenities {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(13em, 1fr));
	gap: 0.15em 1em;
	margin: 0.8em 0 0;
	padding: 0;
	list-style: none;
}

.astyb-amenity > label {
	display: flex;
	align-items: baseline;
	gap: 0.4em;
	cursor: pointer;
}

.astyb-amenity__name {
	flex: 1;
	min-width: 0;
}

.astyb-amenity__count {
	font-size: 0.85em;
	opacity: 0.5;
}

/* ---------------------------------------------------------------------------
   Results
   ------------------------------------------------------------------------ */

.astyb-results__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 1em;
	margin: 0 0 1.2em;
}

/* Class doubled (1.18.4): Avada's `.post-content p { margin: 0 0 20px }`
   (0,1,1) out-weighed a single class. */
.astyb-results__count.astyb-results__count {
	margin: 0;
	font-weight: 600;
}

.astyb-results__sort {
	margin: 0;
}

.astyb-results__empty {
	margin: 2em 0;
	opacity: 0.8;
}

/*
 * Live refresh in progress.
 *
 * ⚠ The old results stay on screen and are dimmed, rather than being cleared to
 * a spinner. Refining a search is a comparison — the visitor is deciding whether
 * the change improved things — and blanking the list takes away the thing they
 * were comparing against. It also stops the page height collapsing and jumping
 * the scroll position, which is the whole complaint this feature answers.
 */
.astyb-results.is-loading {
	position: relative;
	opacity: 0.45;
	transition: opacity 0.12s ease-out;
}

.astyb-results.is-loading::after {
	content: "";
	position: absolute;
	inset: 0;
	cursor: progress;
}

@media (prefers-reduced-motion: reduce) {
	.astyb-results.is-loading {
		transition: none;
	}
}

.astyb-cards {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(16em, 1fr));
	gap: 1.6em;
}

.astyb-card {
	display: flex;
	flex-direction: column;
	min-width: 0;
	border: 1px solid var(--astyb-hair, rgba(0, 0, 0, 0.12));
	border-radius: var(--astyb-radius, 4px);
	overflow: hidden;
}

/* ⚠ 1.18.3 — a card in ANY sidebar: Villagio draws
   `.widget a { border-bottom: 1px dotted currentColor }` (0,1,1) under every
   link in a widget, so a card placed with a Text widget
   (`[astyb_properties card="widget"]`) had dotted lines under its title and
   photograph. Hotel Booking's own widget happened to cancel it; ours must not
   depend on that. (0,2,1) wins; the «Book» button's own frame (0,3,0) is
   stronger still and keeps its bottom edge. */
.astyb-results .astyb-card a {
	border-bottom: 0;
}

/* ★ 1.18.2 — the photograph's link is a block that clips, so a zoom set on the
   Layout screen grows the picture inside its frame instead of over the text.
   Same size as before: the image inside was already a full-width block. */
.astyb-card__image {
	display: block;
	overflow: hidden;
}

/* ★ 1.18.2 — the hover effect and the zoom are generated only when set; a
   visitor who asked the system for less motion gets them WITHOUT the glide —
   the card is simply lifted, the picture simply larger.
   ⚠⚠ Not `transform: none`: that was the first version, and it turned «lifts»
   and «grows» into «shadow only» for everybody with Windows' «Animation
   effects» switched off — which is how Panos found it. Reduced motion asks for
   less animation, not for the effect to be taken away. */
@media (prefers-reduced-motion: reduce) {
	.astyb-card,
	.astyb-card__image img {
		transition: none !important;
	}
}

.astyb-card__image img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

.astyb-card__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	padding: 1em 1.1em 1.2em;
}

.astyb-card__body .astyb-badges {
	margin-bottom: 0.6em;
}

/* ⚠ Class doubled (1.18.4): Avada sizes every heading with
   `.post-content h3` (0,1,1), which beat a single class — the title came out
   32px. (0,2,0) wins over it and over classic.css's heading defaults. */
.astyb-card__title.astyb-card__title {
	margin: 0 0 0.3em;
	font-size: 1em;
	line-height: 1.35;
}

/*
⚠⚠ 1.18.0 — THE TITLE LINK. Villagio names every link in the content column:

    .entry-content a { color: #01bea0; text-decoration: underline }   (0,1,1)

which beat the single-class rule that used to stand here twice over: equal
specificity, and Villagio's sheet printed after ours. The title came out green
and underlined, and — because colour INHERITS and inheritance loses to any rule
naming the element — no text or heading colour set on the Layout screen could
ever reach it. Panos: «our CSS is ignored».

Now: two classes (0,2,1), which win whatever order the sheets load in, and the
colour is handed back to the heading, so the Layout screen's text / heading
colour flows through to the link. ★ `:where()` keeps the colour rule at (0,2,1)
while leaving hover and focus to the theme's `a:hover`, and below the Layout
screen's own «Link colour» rule (0,3,1).
*/
.astyb-card .astyb-card__title a {
	text-decoration: none;
}

.astyb-card .astyb-card__title a:where(:not(:hover, :focus)) {
	color: inherit;
}

.astyb-card__location.astyb-card__location,
.astyb-card__facts.astyb-card__facts {
	margin: 0 0 0.4em;
	font-size: 0.85em;
	opacity: 0.7;
}

/* ★ 1.18.3 — the availability line, spaced like the location line (Panos).
   It had no rule at all, so it took the theme's paragraph gap — 1.5em in the
   content column, 1.78em in a sidebar. Margin only: its own size and colour
   are unchanged. Doubled for `.widget p` — house rule 3. The pill over the
   photograph (0,3,0) still wins with its margin 0. */
.astyb-card__available.astyb-card__available {
	margin: 0 0 0.4em;
}

/* The card's «Title for site» line (1.18.1). ⚠ Doubled — house rule 3. */
.astyb-card__site-title.astyb-card__site-title {
	margin: 0 0 0.3em;
	font-size: 0.9em;
	font-weight: 600;
}

/* The card's own short text (1.18.1). ⚠ Doubled — a `<p>` that may land in a
   widget (house rule 3). */
.astyb-card__summary.astyb-card__summary {
	margin: 0 0 0.5em;
	font-size: 0.9em;
	line-height: 1.45;
}

/* The key facts drawn with icons (1.18.0) — a row, like the property page's.
   ⚠ Doubled: `.widget ul` (0,1,1) would otherwise give it the theme's list
   margin and indent inside a sidebar. See house rule 2. */
.astyb-card__facts--icons.astyb-card__facts--icons {
	display: flex;
	flex-wrap: wrap;
	gap: 0.3em 0.9em;
	margin: 0 0 0.4em;
	padding: 0;
	list-style: none;
}

.astyb-card__fact {
	display: inline-flex;
	align-items: center;
	gap: 0.35em;
}

.astyb-card__fact-icon {
	flex: 0 0 auto;
}

/* The «Book» button (1.18.0).
   ⚠ The row is a `<p>` that can land in a widget — doubled, house rule 3.
   ⚠ Two classes on the link, so Villagio's `.entry-content a` (0,1,1) cannot
   turn it green and underlined; `currentColor` everywhere, so the Layout
   screen's «Link colour» on this section recolours text and outline at once.
   Never `.button` — `mphb-divi` paints those transparent and white. */
.astyb-card__book-row.astyb-card__book-row {
	margin: 0.8em 0 0;
}

/* ⚠ 1.18.3 — the link class is DOUBLED (0,3,0): Hotel Booking's own stylesheet
   has `.widget.widget_mphb_rooms_widget a { border-bottom: none }` (0,2,1),
   which beat the single class inside the sidebar widget and cut the button's
   bottom edge off — Panos's screenshot, «We recommend». */
.astyb-card .astyb-card__book.astyb-card__book {
	display: inline-block;
	padding: 0.4em 1.4em;
	border: 1px solid currentColor;
	border-radius: var(--astyb-radius, 4px);
	color: inherit;
	font-weight: 600;
	line-height: 1.5;
	text-decoration: none;
}

.astyb-card .astyb-card__book.astyb-card__book:is(:hover, :focus) {
	box-shadow: inset 0 0 0 1px currentColor;
	text-decoration: none;
}

/* Push the money to the bottom, so a row of cards lines its prices up however
   long the titles are. */
.astyb-card__body .astyb-loop-prices {
	margin-top: auto;
	padding-top: 0.6em;
}

.astyb-card__quote.astyb-card__quote {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.4em;
	margin: 0.5em 0 0;
	padding-top: 0.5em;
	border-top: 1px dashed var(--astyb-hair, rgba(0, 0, 0, 0.15));
	font-size: 0.9em;
}

.astyb-card__quote-label {
	font-size: 0.85em;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	opacity: 0.65;
}

.astyb-card__quote-total {
	font-weight: 700;
}

.astyb-card__quote-average {
	font-size: 0.85em;
	opacity: 0.7;
}

/* ---------------------------------------------------------------------------
   Pagination
   ------------------------------------------------------------------------ */

.astyb-pagination {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35em;
	margin: 2em 0 0;
}

.astyb-pagination__page {
	display: inline-block;
	min-width: 2.2em;
	padding: 0.35em 0.6em;
	border: 1px solid var(--astyb-hair, rgba(0, 0, 0, 0.15));
	border-radius: 3px;
	text-align: center;
	text-decoration: none;
}

.astyb-pagination__page.is-current {
	border-color: currentColor;
	font-weight: 700;
}

.astyb-pagination__gap {
	padding: 0.35em 0.2em;
	opacity: 0.5;
}

/* ---------------------------------------------------------------------------
   The enquiry form (v1.6.0, milestone B of the v1.5 front-end plan)

   ⚠ Two rules here are load-bearing rather than decorative:

   1. `.astyb-request__trap` hides the honeypot. It must stay hidden on EVERY
      theme, so it is taken out of the flow three ways at once — a real person
      who can see it will fill it in, and their enquiry is then silently
      discarded as a bot's. `display: none` alone is enough for a browser and
      not enough for the handful of bots that read computed styles, hence the
      belt and braces.
   2. `.astyb-request__field--off` is what `request-form.js` toggles. See the
      note in that file for why it is a class and not the `hidden` attribute.

   Everything else borrows the theme's palette through `currentColor`, per the
   house rule at the top of this file.
   ------------------------------------------------------------------------ */

.astyb-request {
	margin: 1.5em 0 0;
}

/* Class doubled (1.18.4) — a heading; see `.astyb-card__title`. */
.astyb-request__title.astyb-request__title {
	margin: 0 0 0.6em;
	font-size: 1.15em;
}

.astyb-request__form {
	display: grid;
	gap: 0.85em;
	max-width: 40em;
}

.astyb-request__field {
	display: flex;
	flex-direction: column;
	gap: 0.25em;
	margin: 0;
}

.astyb-request__field label {
	font-size: 0.92em;
	font-weight: 600;
}

.astyb-request__field input[type="text"],
.astyb-request__field input[type="email"],
.astyb-request__field input[type="tel"],
.astyb-request__field input[type="date"],
.astyb-request__field input[type="number"],
.astyb-request__field select,
.astyb-request__field textarea {
	width: 100%;
	max-width: 100%;
	box-sizing: border-box;
}

/* ⚠ Toggled by request-form.js — see the header note. */
.astyb-request__field--off {
	display: none;
}

.astyb-request__dates {
	display: grid;
	gap: 0.85em;
	grid-template-columns: repeat(auto-fit, minmax(11em, 1fr));
}

/*
⚠ The container query, not a media query, and for the same reason the search
tabs needed one: this form renders in the content column AND in a 283px
sidebar widget, where the VIEWPORT IS IDENTICAL. A `@media` rule cannot tell
the two apart; only the container can.
*/
.astyb-request {
	container-type: inline-size;
}

@container (max-width: 24em) {
	.astyb-request__dates {
		grid-template-columns: 1fr;
	}
}

.astyb-request__field--consent label {
	display: flex;
	align-items: flex-start;
	gap: 0.5em;
	font-weight: 400;
	line-height: 1.4;
}

.astyb-request__field--consent input {
	margin-top: 0.2em;
	flex: 0 0 auto;
}

.astyb-request__required {
	border: 0;
	text-decoration: none;
	opacity: 0.6;
}

.astyb-request__hint,
.astyb-request__privacy {
	margin: -0.4em 0 0;
	font-size: 0.85em;
	opacity: 0.7;
}

.astyb-request__error {
	font-size: 0.85em;
	font-weight: 600;
	color: #b32d2e;
}

.astyb-request__error--form {
	margin: 0 0 0.8em;
	padding: 0.6em 0.8em;
	border-left: 3px solid #b32d2e;
	background: rgba(179, 45, 46, 0.06);
}

.astyb-request__thanks {
	margin: 0;
	padding: 0.9em 1em;
	border-left: 3px solid currentColor;
	background: rgba(0, 0, 0, 0.04);
	font-weight: 600;
}

.astyb-request__actions {
	margin: 0;
}

/* ⚠ The honeypot. Hidden three ways — see the header note above. */
.astyb-request__trap {
	position: absolute !important;
	left: -9999px !important;
	width: 1px !important;
	height: 1px !important;
	overflow: hidden !important;
	opacity: 0 !important;
	pointer-events: none !important;
}

/* ---------------------------------------------------------------------------
   v1.9 — the card's parts are wrapped in section elements now
   ---------------------------------------------------------------------------
   ⚠⚠ `margin-top: auto` is what lines the price up along the bottom of every
   card in a row, however ragged their text. It only works on a **flex item of
   `.astyb-card__body`**, and wrapping each part in `.astyb-section` stopped the
   price being one — so the rule moves up a level to the wrapper. Without this
   the prices sit wherever the text above them ends, and a grid of cards looks
   subtly broken in a way that reads as a CSS bug rather than a markup change.
   ------------------------------------------------------------------------ */

.astyb-card__body > .astyb-section--price {
	margin-top: auto;
	padding-top: 0.6em;
}

.astyb-card__body > .astyb-section--price .astyb-loop-prices {
	margin-top: 0;
	padding-top: 0;
}

/* The section wrappers are layout-transparent by default: no box of their own
   until somebody gives them one from Asty Booking → Layout. */
.astyb-card__body > .astyb-section,
.astyb-results__bar > .astyb-section {
	min-width: 0;
}

/* ---------------------------------------------------------------------------
   Which side the filter column sits on (v1.9)
   ---------------------------------------------------------------------------
   ⚠⚠ These override VILLAGIO's own two-column floats, which is the last rung of
   the integration ladder and the only place this plugin uses it. On this install
   the search form is the theme's `sidebar-1` widget, so its side is the theme's
   decision and there is no hook between us and it. Villagio, above 62em:

       .content-area:not(.full-width) { float: left;  width: 71.7%; padding-right: 2.1875em }
       .site-content .widget-area     { float: right; width: 28.3%; padding-left:  2.1875em }

   ★ Fails safe: if a future Villagio uses flex or grid, `float` is ignored on a
   flex item and the columns fall back to the theme's own order — the setting
   stops working rather than breaking the page.

   ⚠ The widths are deliberately NOT restated. Only the side and the inner gutter
   are flipped, so a Villagio release that changes its proportions keeps them.

   ⚠ Below 62em Villagio stacks the columns and neither rule applies, which is
   correct: on a telephone the filters belong above the results either way.
   ------------------------------------------------------------------------ */

@media screen and (min-width: 62em) {
	.astyb-filters-left .content-area:not(.full-width) {
		float: right;
		padding-right: 0;
		padding-left: 2.1875em;
	}

	.astyb-filters-left .site-content .widget-area {
		float: left;
		padding-left: 0;
		padding-right: 2.1875em;
	}

	/* Stated rather than assumed: «right» must survive a theme whose own
	   default is the other way round. */
	.astyb-filters-right .content-area:not(.full-width) {
		float: left;
		padding-left: 0;
		padding-right: 2.1875em;
	}

	.astyb-filters-right .site-content .widget-area {
		float: right;
		padding-right: 0;
		padding-left: 2.1875em;
	}
}

/* ---------------------------------------------------------------------------
   ★ 1.18.4 — the filter column WE draw (`Front::with_filter_column()`)

   When the theme has no sidebar showing the search widget (Avada), the results
   list brings the form itself. Villagio's proportions, restated because here
   they are ours: 28.3% / 71.7%, a 2.1875em gutter on each side of the seam.
   The form is first in the markup, so one column = filters above results.
   ------------------------------------------------------------------------ */

.astyb-filters {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 2rem;
}

@media screen and (min-width: 62em) {
	.astyb-filters--left {
		grid-template-columns: minmax(0, 28.3fr) minmax(0, 71.7fr);
		column-gap: 4.375em;
	}

	.astyb-filters--right {
		grid-template-columns: minmax(0, 71.7fr) minmax(0, 28.3fr);
		column-gap: 4.375em;
	}

	.astyb-filters--right .astyb-filters__side {
		order: 2;
	}
}

/* ---------------------------------------------------------------------------
   ★ 1.14.0 — the host's checkout, inside our `.astyb-checkout` wrapper

   `mphb-divi` (active on live) paints `.mphb_sc_checkout-wrapper .button`
   transparent with a 2px border in an inherited WHITE — made for a Divi colour
   scheme. On Villagio «Book Now» was an empty rectangle: a visitor who reached
   the checkout could not see how to finish. Scoped to our wrapper (see
   `Direct_Booking::wrap_checkout()`), so no host selector is styled on its
   own; (0,3,0) beats its (0,2,0). No colour named: outlined in the text colour.
   ------------------------------------------------------------------------ */

.astyb-checkout .mphb_sc_checkout-wrapper .button {
	padding: 0.7em 1.4em;
	border: 1px solid currentColor;
	border-radius: 12px;
	color: inherit;
	background: transparent;
}

.astyb-checkout .mphb_sc_checkout-wrapper .button:hover,
.astyb-checkout .mphb_sc_checkout-wrapper .button:focus-visible {
	background: color-mix(in srgb, currentColor 12%, transparent);
}

/* ---------------------------------------------------------------------------
   ★ 1.18.6 — our accommodation-category page (`Category_View`)

   The category's name and description over the results. The name is the
   page's only heading: Avada prints none on an archive.
   ------------------------------------------------------------------------ */

.astyb-category__header {
	margin: 0 0 1.5em;
}

.astyb-category__title.astyb-category__title {
	margin: 0 0 0.3em;
}

.astyb-category__description > :last-child {
	margin-bottom: 0;
}
