/*
 * Track A — product page redesign.
 *
 * Loaded ONLY when tourflow_mobile_layout = description-first. Mobile-first:
 * base rules are the ≤921px layout, and @media (min-width: 922px) carries
 * desktop. This is the opposite convention to tourflow-frontend.css, which is
 * desktop-first with max-width queries and is deliberately NOT converted —
 * this sheet loads after it and overrides by cascade.
 *
 * Astra's breakpoint is 921px. Do not add a second layout breakpoint.
 */

/* ==========================================================================
   A1 · Reorder — description before the booking form, unconditional
   --------------------------------------------------------------------------
   `output_hero_section()` already emits `.tourflow-body-left` (description)
   before `.tourflow-body-right` (booking form) in the DOM. `order: 1` / `2`
   simply restores that natural DOM order, so it is correct at every width —
   not scoped to a breakpoint.

   This has to be unconditional rather than confined to ≤921px: the classic
   rules this overrides live inside tourflow-frontend.css's max-width:1024px
   block (`:450-451`), so a ≤921px-only override would leave the 922–1024px
   band unopposed — form still first, description still second. Those classic
   blocks (`:450-451` and `:483-489`) stay untouched so that path is unchanged;
   this sheet loads after and wins by cascade.

   The base grid at tourflow-frontend.css:199-208 is a two-column `3fr 2fr`
   with no `order` declarations, so this rule changes nothing on desktop.
   ========================================================================== */
.tourflow-body-left  { order: 1; }
.tourflow-body-right { order: 2; }

/* ==========================================================================
   A2 · Sticky CTA — mobile only
   --------------------------------------------------------------------------
   Reuses the existing button and price typography rather than introducing a
   new one: visual consistency is a hard requirement of the approval.

   Fix round 1/5, Critical 4: the first version of this block specced a WHITE
   bar (`background: #fff`) with no explicit `color` on the price element, so
   the price inherited this dark-themed site's near-white body text — near
   white on white, effectively invisible. Measured live:
   `.tourflow-sticky-cta` background rgb(255,255,255) vs price
   color rgb(236,241,254). A white bar was also wrong on its own terms on a
   dark-navy site. Colours below are taken from the approved prototype,
   `docs/prototypes/2026-08-09-booking-flow-prototype.html:658-682`
   (`--tf-line: rgba(255,255,255,.12)` at :195).

   Task 3f (2026-08-10): the class names now ADOPT the prototype's own
   vocabulary (`.tf-cta-price` / `.tf-cta-amount` / `.tf-cta-meta` /
   `.tf-cta-button`), reversing the naming decision made in Task 3. See the
   task-3f brief: diverging from the prototype's class names is what caused
   every defect that prompted this batch, and a mixed vocabulary would have
   been worse than either convention alone. The dark bar and the explicit
   white price colour fixed in Task 3's round are kept unchanged — only the
   selectors and the meta line are new.
   ========================================================================== */
.tourflow-sticky-cta {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 998; /* below Joinchat's own layer, above page content */
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 14px;
	padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
	background: rgba(13, 18, 36, .94);
	border-top: 1px solid rgba(255, 255, 255, .12);
	backdrop-filter: saturate(160%) blur(10px);
	-webkit-backdrop-filter: saturate(160%) blur(10px);
	transform: translateY(0);
	transition: transform .22s ease;
}

.tourflow-sticky-cta.is-hidden {
	transform: translateY(110%);
}

.tourflow-sticky-cta .tf-cta-price {
	flex: 1 1 auto;
	min-width: 0;
}

.tourflow-sticky-cta .tf-cta-amount {
	display: block;
	color: #fff;
	font-weight: 700;
	line-height: 1.2;
}

/* Muted grey against the dark bar. Reuses the same rgba(255,255,255,.62)
   token the spec bar (Task 3c) uses for its own labels, rather than the
   prototype's --tf-muted (#99a6bd) — that variable is tuned for the
   prototype's own dark-navy shade, not this site's; the white-based token is
   already proven legible here (see the Critical 4 fix note above) and keeps
   one muted-text convention across both new components.
   `white-space: nowrap` + ellipsis per the brief step 4 — verified at 320px
   in Spanish, see the task-3fcd report. */
.tourflow-sticky-cta .tf-cta-meta {
	display: block;
	margin-top: 2px;
	font-size: 11.5px;
	color: rgba(255, 255, 255, .62);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* The action reuses the booking button's shape and colour. If
   .tourflow-book-now-button's declarations change, this must follow. */
.tf-cta-button {
	flex: 0 0 auto;
	background: #02BEEC;
	color: #fff;
	border: 0;
	border-radius: 4px;
	padding: 12px 22px;
	font-weight: 700;
	cursor: pointer;
}

/* Task 4b — the sticky CTA scrolls to `.tourflow-booking-fields-container`
   (the calendar's container, both calendar modes) rather than the form top,
   so it lands on the thing you book with instead of a heading four screens
   above it. `block: 'start'` puts the target's top at the viewport's y=0,
   but the site header is `position: fixed` and 90px tall, so without this
   the calendar scrolls to right underneath it. Fixed in CSS, not by
   compensating in the scroll maths: scroll-margin-top is what the property
   is for. */
@media (max-width: 921px) {
	.tourflow-booking-fields-container { scroll-margin-top: 106px; }
}

/* Joinchat's WhatsApp float overlaps the booking form by 23×40px. Lift it
   clear of the sticky bar rather than hiding it — it is a live support channel.

   `--bottom` is Joinchat's OWN positioning variable, not one we invent:
   joinchat.css:8 declares `--bottom: var(--sep)` and :30 consumes it as
   `bottom: var(--bottom)`. Overriding it is therefore the supported lever, and
   it keeps the plugin's internal math coherent — :334 sizes the chatbox with
   `calc(var(--vh) - var(--bottom) - var(--sep))`, so a margin hack would move
   the button while leaving the chatbox measuring against the old position.
   Set the variable; do NOT also add margin-bottom, which would double-shift. */
.joinchat {
	--bottom: 84px;
}

@media (min-width: 922px) {
	/* Desktop has the booking form in a sticky column; the bar is redundant,
	   so Joinchat returns to its own default position. */
	.tourflow-sticky-cta { display: none; }
	.joinchat { --bottom: var(--sep); }
}

/* A6's desktop unclamp used to live HERE, in this A2 block — wrong section,
   and load-bearing: it put the override BEFORE the base ≤921px-intended
   `.is-clamped .tf-desc-body` rule (A6, below) instead of after it. Both
   declare the exact same selector at the same specificity (0,3,0), unscoped,
   so source order alone decided — and the base rule, appearing LATER in the
   file, silently won on every width, including desktop. Bug found by Ramón
   2026-08-11: 577px of the description (the whole "incluye" list) was
   clamped, faded AND had no toggle to expand it, at 1440px.
   Moved to directly follow the rule it overrides — matching this file's own
   mobile-first convention (base unscoped rule, then a LATER min-width query
   overrides it) that A5's spec-bar rules just above already follow
   correctly. Checked every other selector in this file for the same
   base-after-override shape; this was the only instance. */

/* ==========================================================================
   A4 · Mobile hero tightening — ≤921px only
   --------------------------------------------------------------------------
   Measured before this block: banner 420px + circle 300px + a hero price, so
   the description started at y=837 and no part of it reached a 844px screen.
   A1 put the description first; this is what makes that visible.

   Values come from the approved prototype. Its MARKUP does not port — it draws
   the banner as an inline SVG that production does not have — so these target
   production's own elements instead: body.single-product::before is the banner,
   .tourflow-hero-image-wrapper is the circle.

   Desktop is deliberately absent from this block. The prototype's standard is
   that desktop stays byte-identical; Task 5 owns desktop hero values.
   ========================================================================== */
@media (max-width: 921px) {
	/* One source for the banner height: the ::before that paints it and the
	   padding that positions content over it both read this. */
	body.single-product { --tf-banner-h: clamp(150px, 40vw, 190px); }

	/* The banner band. 40vw keeps it proportional on small phones; the clamp
	   stops it collapsing on a 320px screen or ballooning near the breakpoint.

	   !important is required here, and here only: Astra's Additional CSS
	   (wp_get_custom_css()) defines this exact selector — body.single-product
	   ::before { height: clamp(420px, 55vw, 750px); } — with no media query
	   and no !important of its own. Same selector, same specificity, but it is
	   printed inline in <head> AFTER this stylesheet's <link>, so plain source
	   order lets it win the cascade and silently keeps the banner at 420px.
	   Measured: without !important the banner stays 420px on a 390px viewport
	   even with this rule present. The numeric values are unchanged from the
	   brief/prototype — only the specificity mechanics differ. */
	body.single-product::before {
		height: var(--tf-banner-h) !important;
	}

	/* Astra's Customizer pins .site-content at 250px, which does not track the
	   banner — so shrinking the banner left 90px of dead space. Our body class
	   (tourflow-layout-redesign, added via the body_class filter only when
	   should_apply() is true) outranks it on specificity: (0,2,1) vs (0,2,0). */
	body.tourflow-layout-redesign .site-content {
		margin-top: 0 !important;
	}

	/* The prototype starts the circle at 60% of the banner height so it
	   overlaps the banner's base. max() guarantees it still clears the fixed
	   site header (measured 90px tall at 320–428px wide on Local) if the
	   clamp ever resolves smaller. */
	.tourflow-hero-header {
		padding-top: max(100px, calc(var(--tf-banner-h) * .60));
	}

	/* The circular product image. 36vw tracks the banner's proportions. */
	.tourflow-hero-image-wrapper {
		width: min(36vw, 132px);
		height: min(36vw, 132px);
	}

	/* The price is not removed from the page — it moves. The sticky CTA shows
	   it from scroll depth 0, so rendering it here too is the same number
	   twice on one screen. Hiding it is what buys the last ~35px. */
	.tourflow-hero-wrapper p.price {
		display: none;
	}
}

/* ==========================================================================
   A5 · Hero spec bar — Desde / Personas / Duración
   --------------------------------------------------------------------------
   Ported from the approved prototype, `docs/prototypes/2026-08-09-booking-
   flow-prototype.html:398-422`. The prototype's comment records this as a
   client requirement: the placard stays over the hero.

   Two prototype-local custom properties have no production equivalent and
   are substituted here:
     --tf-radius (10px)      -> literal 10px, the prototype's own value.
     --tf-font-data           -> the prototype's own monospace stack, kept
                                  literally (ui-monospace, SFMono-Regular,
                                  'SF Mono', Menlo, Consolas, monospace) for
                                  tabular figures on the price/duration cells
                                  — production has no equivalent token to
                                  substitute, and this is a legitimate,
                                  self-contained design choice rather than an
                                  invented dependency.
   Every other value (colours, borders) already exists in this file's own
   established vocabulary (rgba(255,255,255,.16) borders, rgba(8,12,24,.62)
   dark glass fill) and is reused rather than re-derived.
   ========================================================================== */
.tourflow-spec-bar {
	align-self: stretch;
	width: 100%;
	max-width: 640px;
	margin: 18px 0 0;
	display: flex;
	align-items: stretch;
	gap: 0;
	border: 1px solid rgba(255, 255, 255, .16);
	border-radius: 10px;
	overflow: hidden;
	background: rgba(8, 12, 24, .62);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
	text-align: left;
}

.tourflow-spec-bar .tf-spec {
	flex: 1 1 0;
	min-width: 0;
	padding: 10px 12px;
	border-right: 1px solid rgba(255, 255, 255, .14);
}

.tourflow-spec-bar .tf-spec:last-child {
	border-right: 0;
}

.tourflow-spec-bar .tf-spec-k {
	display: block;
	font-size: 9.5px;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .62);
	margin-bottom: 3px;
}

.tourflow-spec-bar .tf-spec-v {
	display: block;
	font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
	font-size: 14px;
	font-weight: 600;
	color: #fff;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.tourflow-spec-bar .tf-spec-v.is-price {
	color: #02BEEC;
}

/* Task 3h (2026-08-10) — desktop shows the price once, in the hero, not the
   spec bar. There is no sticky CTA at ≥922px to carry the price instead, so
   the hero keeps its 42px price and the placard drops its price cell rather
   than repeating the number at 14px. Server-side class rather than `:has()`
   — this project's hard requirement includes older in-app webviews (Facebook,
   Instagram) where `:has()` support is not guaranteed. */
@media (min-width: 922px) {
	.tourflow-spec-bar .tf-spec--price {
		display: none;
	}
}

/* Task 5b (2026-08-10) — now nested as the last child of
   .tourflow-header-right (class-tourflow-frontend.php:output_hero_section())
   instead of a sibling row below the circle. That row cost 119px of hero
   height for a 61px element; nested here it fills the slack beside the
   300px circle instead. The base .tourflow-spec-bar rule's max-width: 640px
   is too wide once it shares the ~810px text column with the title/price —
   capped at 520px, with a small gap below the price. */
@media (min-width: 922px) {
	.tourflow-hero-header .tourflow-spec-bar {
		max-width: 520px;
		margin-top: 20px;
	}
}

/* ==========================================================================
   A6 · Description clamp — "Ver todo lo que incluye"
   --------------------------------------------------------------------------
   Ported from prototype :456-468. Measured on Local: Piloto's
   .tourflow-body-left is 853px tall — tightening the hero (A4) and then
   leaving 853px of unclamped text still pushes the booking form off-screen.
   The prototype's own comment: "Collapsed description keeps the booking
   form reachable at 44.7% scroll depth."

   Colour reuses this file's own established teal (#02BEEC, same as the
   sticky CTA button and the spec bar's price cell) rather than the
   prototype's --tf-teal (#2ec6ea), for the same visual-consistency reason
   given in the A2 and A5 sections above.
   ========================================================================== */
.tourflow-description-content.is-clamped .tf-desc-body {
	max-height: 300px;
	overflow: hidden;
	-webkit-mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
	mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
}

.tf-desc-toggle {
	appearance: none;
	background: none;
	border: 0;
	padding: 8px 0 0;
	color: #02BEEC;
	font: inherit;
	font-size: 13.5px;
	font-weight: 700;
	cursor: pointer;
}

.tf-desc-toggle::after {
	content: " ↓";
}

.tourflow-description-content:not(.is-clamped) .tf-desc-toggle::after {
	content: " ↑";
}

/* Desktop has room for the full description (prototype :1066-1067), so the
   clamp, its mask and the toggle all drop out entirely. Placed AFTER the
   base rule above on purpose — see the note in the A2 section (~line 158)
   for the bug this ordering fixes: same selector, same specificity, and an
   override declared earlier in the file loses to a base rule declared later. */
@media (min-width: 922px) {
	.tourflow-description-content.is-clamped .tf-desc-body {
		max-height: none;
		-webkit-mask-image: none;
		mask-image: none;
	}
	.tf-desc-toggle { display: none; }
}

/* ==========================================================================
   A3 · Fecha Abierta — choice cards, not a radio row
   --------------------------------------------------------------------------
   .tf-booking-type-btn / .tf-btn-visual already exist and already carry the
   selected state (tourflow-frontend.css:3099-3142). This adds the two-line
   interior only — the borders, colours and checked state are inherited, which
   is what keeps the redesign visually consistent with the rest of the form.
   ========================================================================== */
.tf-booking-type-options {
	display: grid;
	grid-template-columns: 1fr;
	gap: 10px;
}

.tf-booking-type-btn .tf-btn-visual {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 4px;
	text-align: left;
}

.tf-btn-title {
	font-weight: 700;
	line-height: 1.25;
}

.tf-btn-desc {
	font-size: .85em;
	line-height: 1.35;
	opacity: .75;
}

/* The 90-day validity is called out inside the Fecha Abierta card itself
   (prototype :1403) — bumped back to full opacity/weight so it reads as a
   fact, not a continuation of the dimmer description line above it. */
.tf-validity {
	display: inline-block;
	margin-top: 2px;
	font-weight: 600;
	opacity: 1;
}

/* Reassurance line under the form heading — answers "will I be charged now?"
   before the wizard, which nothing else on the page addresses. */
.tf-form-note {
	margin: -6px 0 16px;
	font-size: .85em;
	opacity: .75;
}

/* This box's inline display:none was dropped in class-tourflow-frontend.php
   (Track A Task 4) so booking-frontend.js's change handler could show it once
   Fecha Abierta is selected. It still belongs to the SELECTED state, not to
   first paint — the "surface the 90-day validity before selection" spec
   requirement is met by the always-visible .tf-validity span inside the
   Fecha Abierta card itself. The bug where this box also rendered on load in
   booking mode (nothing set an initial state) is fixed in booking-frontend.js,
   not here. */
.tourflow-voucher-info {
	margin-top: 12px;
}

/* Bug 2 (2026-08-11, Ramón): WooCommerce core reserves padding-left: 3.5em on
   .woocommerce-info for its ::before icon (core CSS: position: absolute;
   left: 1.5em). tourflow-frontend.css's site-wide, low-specificity
   `.woocommerce-message, .woocommerce-info, .woocommerce-error { padding: 14px
   18px; }` (added for the TourFlow glass look) collapses that to a uniform
   18px, so text now starts under the icon (measured: icon spans x 21.9-36.9px,
   text starts at 18px) — on EVERY .woocommerce-info/-message/-error notice
   site-wide, not just this one. Track A only exposed it here, by making a box
   that used to be display:none visible. Fixed here (flag-scoped, higher
   specificity, no !important needed) rather than in the classic sheet, which
   would break the byte-identical rollback guarantee — the site-wide defect on
   cart/checkout/account notices is Ramón's call and is reported separately,
   not fixed by this change. */
.tourflow-voucher-info .woocommerce-info {
	padding-left: 44px;
}

@media (min-width: 922px) {
	.tf-booking-type-options { grid-template-columns: 1fr 1fr; }
}

/* ==========================================================================
   Desktop — ≥922px
   --------------------------------------------------------------------------
   Ported from the prototype's single @media block, product-page rules only.
   Wizard rules from that block belong to Track B and are deliberately absent.
   ========================================================================== */
@media (min-width: 922px) {
	/* ⚠️ `!important` here is load-bearing, not laziness.
	   tourflow-frontend.css:444-448 declares
	     .tourflow-hero-body { grid-template-columns: 1fr !important; }
	   inside @media (max-width: 1024px) — "stack sooner on tablets". An
	   !important is only beaten by another !important, so without this the
	   redesign's two-column grid silently loses across the whole 922–1024px
	   band and those widths render single-column. Specificity cannot fix it;
	   only matching importance can, and at equal importance and specificity
	   this sheet wins because it loads second.
	   Remove the !important only if that classic block is ever narrowed to
	   max-width: 921px. */
	.tourflow-hero-body {
		display: grid;
		grid-template-columns: 1.05fr 1fr !important;
		gap: 30px;
		max-width: 1180px;
		margin: 0 auto;
		padding: 30px 32px 40px;
		align-items: start;
	}

	.tourflow-body-left  { padding: 0; }

	/* Bug 5 (2026-08-11, Ramón): .tourflow-description-content carries
	   width: 60%; flex: 1; from tourflow-frontend.css:529 — a leftover from
	   when the description and the booking form were flex SIBLINGS splitting
	   one row 60/40. Task 3d's clamp wrapper reused the prototype's class
	   name, which already carried that styling, and it now lives INSIDE
	   .tourflow-body-left, itself already half the grid — 60% of 50%, so the
	   description used only 334px of a 556px column (334.734 / 556.234 =
	   exactly .60). tourflow-frontend.css:566 already resets this to 100%,
	   but only inside its own max-width: 921px block, which is why mobile
	   was never affected. Same specificity (0,1,0) as the rule it overrides,
	   no !important on either side — this sheet wins on load order alone, as
	   long as nothing LATER in this file re-declares the same selector (see
	   the Bug 3 fix above this block for what happens when that's not true;
	   checked — nothing later here touches .tourflow-description-content's
	   width or flex). Do not edit tourflow-frontend.css: that is the classic
	   path the byte-identical rollback guarantee depends on. */
	.tourflow-description-content { width: 100%; flex: none; }

	/* The form follows the reader down a long description. 88px clears
	   Astra's sticky header. */
	.tourflow-body-right {
		padding: 0;
		position: sticky;
		top: 88px;
	}
}
