/* ==========================================================================
   Components — structural + visual styles for reusable UI pieces.
   ========================================================================== */

/* Buttons — premium: soft lift + shadow on hover, a real press state (not
   just a hover state minus itself), primary gets a tinted glow shadow
   instead of a flat generic one. */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-md);
  border: 2px solid transparent;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-200);
  text-decoration: none;
  cursor: pointer;
  min-height: 48px; /* accessible tap target */
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), background-color var(--transition-fast), border-color var(--transition-fast);
  will-change: transform;
}

.btn:hover {
  transform: translateY(-3px);
}

.btn:active {
  transform: translateY(-1px) scale(0.98);
  transition-duration: 80ms;
}

.btn:focus-visible {
  transform: translateY(-3px);
}

.btn--primary {
  background-color: var(--color-primary);
  color: var(--color-white);
  box-shadow: 0 4px 14px rgba(237, 42, 145, 0.22);
}

.btn--primary:hover,
.btn--primary:focus-visible {
  background-color: var(--color-primary-dark);
  box-shadow: var(--shadow-primary);
}

.btn--secondary {
  background-color: transparent;
  border-color: var(--color-ink);
  color: var(--color-ink);
}

.btn--secondary:hover,
.btn--secondary:focus-visible {
  background-color: var(--color-ink);
  color: var(--color-white);
  box-shadow: var(--shadow-md);
}

/* Used on dark surfaces (hero, cta-banner) — border needs to be visible
   against ink/photo backgrounds, and hover fills white-on-dark instead of
   dark-on-dark. */
.btn--on-dark {
  border-color: rgba(255, 255, 255, 0.55);
  color: var(--color-white);
}

.btn--on-dark:hover,
.btn--on-dark:focus-visible {
  background-color: var(--color-white);
  border-color: var(--color-white);
  color: var(--color-ink);
  box-shadow: var(--shadow-lg);
}

.btn--tertiary {
  background-color: transparent;
  color: var(--color-text-muted);
}

.btn--lg {
  padding: var(--space-4) var(--space-8);
  font-size: var(--fs-300);
  min-height: 56px;
}

/* Header — fixed (not sticky): removed from flow so a hero can extend
   full-bleed behind it (pages without a hero reserve --header-height of
   top padding instead, see base.css). Permanently glass: dark, blurred,
   translucent on every page from first paint — this is what makes the nav
   read as premium chrome rather than a plain bar, and it means the exact
   same header design works identically whether it's floating over a photo
   or over a solid page-header band. On scroll it intensifies (more opaque
   + shadow) via [data-scrolled="true"], toggled by
   assets/js/header-scroll.js watching a sentinel element
   (IntersectionObserver — no scroll-listener jank). */
.site-header {
  position: fixed;
  top: 0;
  inset-inline: 0;
  z-index: var(--z-header);
  height: var(--header-height);
  display: flex;
  align-items: center;
  background-color: rgba(14, 14, 16, 0.38);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  backdrop-filter: blur(18px) saturate(140%);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  transition: background-color var(--transition-standard), box-shadow var(--transition-standard), border-color var(--transition-standard);
}

.site-header[data-scrolled="true"] {
  background-color: rgba(12, 12, 14, 0.86);
  border-bottom-color: transparent;
  box-shadow: var(--shadow-md);
}

.site-header__inner {
  position: relative; /* anchors the mobile nav dropdown below */
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.site-header__logo {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  /* Belt-and-suspenders against the logo ever dictating header height:
     the flex item itself is capped independently of its content's
     intrinsic size (859x311 native — if the image ever rendered at
     anywhere near that, it would break the whole navbar, which is
     exactly what happened in production off stale cached CSS). */
  max-height: var(--header-height);
  overflow: hidden;
}

/* Logo sizing is deliberately NOT left to the image's natural dimensions
   (859x311) — max-height + max-width caps it at every breakpoint, with
   width/height:auto so it scales down proportionally rather than
   stretching or cropping, and object-fit:contain as a second guarantee
   for the same. This must survive even if some other rule or a stale
   cache momentarily fails to apply — the max-* pair is the hard ceiling. */
.site-header__logo-img {
  display: block;
  width: auto;
  height: auto;
  max-height: 34px;
  max-width: 140px;
  object-fit: contain;
}

@media (min-width: 600px) {
  .site-header__logo-img {
    max-height: 40px;
    max-width: 160px;
  }
}

@media (min-width: 900px) {
  .site-header__logo-img {
    max-height: 44px;
    max-width: 180px;
  }
}

.site-header__menu-toggle {
  min-width: 44px;
  min-height: 44px;
  background: none;
  border: none;
  cursor: pointer;
  position: relative;
}

/* Hamburger icon drawn in pure CSS (three bars) so it never depends on a
   missing icon asset, and can cleanly morph into a close (X) state. */
.site-header__menu-toggle::before,
.site-header__menu-toggle::after,
.site-header__menu-toggle span[data-bar] {
  content: '';
  position: absolute;
  left: 50%;
  width: 22px;
  height: 2px;
  background-color: var(--color-white);
  transform: translateX(-50%);
  transition: transform var(--transition-fast), opacity var(--transition-fast), top var(--transition-fast);
}

.site-header__menu-toggle::before { top: 16px; }
.site-header__menu-toggle span[data-bar] { top: 22px; }
.site-header__menu-toggle::after { top: 28px; }

.site-header__menu-toggle[aria-expanded="true"]::before {
  top: 22px;
  transform: translateX(-50%) rotate(45deg);
}

.site-header__menu-toggle[aria-expanded="true"] span[data-bar] {
  opacity: 0;
}

.site-header__menu-toggle[aria-expanded="true"]::after {
  top: 22px;
  transform: translateX(-50%) rotate(-45deg);
}

@media (min-width: 900px) {
  .site-header__menu-toggle { display: none; }
}

/* Desktop-only booking CTA (Phase 2) — mobile already has "Reservar" in
   the sticky bottom bar, so showing it here too would be redundant. */
.site-header__cta {
  display: none;
}

@media (min-width: 900px) {
  .site-header__cta {
    display: inline-flex;
  }
}

/* Nav — collapsed by default on mobile, toggled via assets/js/mobile-menu.js
   setting data-nav-open on #primary-nav; always visible from 900px up. */
.site-nav {
  display: none;
  position: absolute;
  inset-inline: 0;
  top: 100%;
  background-color: var(--color-ink);
  box-shadow: var(--shadow-lg);
}

.site-nav[data-nav-open="true"] {
  display: block;
  animation: nav-drop-in var(--transition-standard) var(--ease-premium) both;
}

@keyframes nav-drop-in {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (min-width: 900px) {
  .site-nav {
    display: block;
    position: static;
    box-shadow: none;
    background-color: transparent;
  }
}

.site-nav__list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 0;
  padding: var(--space-2) 0;
}

.site-nav__link {
  display: block;
  padding: var(--space-4) var(--space-6);
  min-height: 44px;
  color: var(--color-white);
  text-decoration: none;
  font-weight: 500;
  position: relative;
}

@media (min-width: 900px) {
  .site-nav__list {
    flex-direction: row;
    gap: var(--space-6);
    padding: 0;
  }

  .site-nav__link {
    padding: 0;
    min-height: auto;
  }

  /* Animated underline on hover — a small, elegant micro-interaction
     rather than an instant color swap. */
  .site-nav__link::after {
    content: '';
    position: absolute;
    left: 0;
    right: 100%;
    bottom: -6px;
    height: 2px;
    background-color: var(--color-primary);
    transition: right var(--transition-standard) var(--ease-premium);
  }

  .site-nav__link:hover::after,
  .site-nav__link[aria-current="page"]::after {
    right: 0;
  }
}

/* Mobile sticky CTA bar — present on every page per PROJECT.md §6 CRO strategy.
   viewport-fit=cover (set in partials/head.php) is required for the
   safe-area-inset-bottom env() below to resolve to anything but 0 on
   notched devices — without it this rule is silently inert. */
.mobile-cta-bar {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: var(--z-mobile-cta);
  display: flex;
  background-color: var(--color-ink);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.18);
}

@media (min-width: 900px) {
  .mobile-cta-bar { display: none; }
}

.mobile-cta-bar__item {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--mobile-cta-height);
  color: var(--color-white);
  text-decoration: none;
  font-weight: 600;
  transition: background-color var(--transition-fast);
}

.mobile-cta-bar__item:active {
  background-color: rgba(255, 255, 255, 0.08);
}

.mobile-cta-bar__item--primary {
  background-color: var(--color-primary);
}

.mobile-cta-bar__item--primary:active {
  background-color: var(--color-primary-dark);
}

/* Phase 2 priority: WhatsApp + Reservar stay flex:1 (wide, labeled);
   Llamar shrinks to an icon-only tap target (still ≥44px). */
.mobile-cta-bar__item--icon-only {
  flex: 0 0 var(--mobile-cta-height);
}

.mobile-cta-bar__item--icon-only img {
  filter: invert(1); /* white icon on the bar's dark background */
}

/* Compensates for the fixed CTA bar so it never overlaps/obscures the last
   content on the page (footer links were unreachable behind it otherwise). */
@media (max-width: 899px) {
  body {
    padding-bottom: calc(var(--mobile-cta-height) + env(safe-area-inset-bottom, 0px));
  }
}

/* Footer */
.site-footer {
  background-color: var(--color-ink);
  color: var(--color-white);
  padding-block: var(--space-24) var(--space-16);
}

.site-footer a {
  color: var(--color-white);
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--color-primary);
}

.site-footer__inner {
  display: grid;
  gap: var(--space-8);
}

.site-footer__logo {
  display: inline-block;
  margin-bottom: var(--space-4);
}

.site-footer__logo img {
  display: block;
  height: 38px;
  width: auto;
}

.site-footer__business-name {
  font-family: var(--font-display);
  font-size: var(--fs-400);
  font-weight: 700;
  margin-bottom: var(--space-2);
}

.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.site-footer__copyright {
  color: rgba(255, 255, 255, 0.5);
  font-size: var(--fs-100);
  margin-top: var(--space-8);
  padding-top: var(--space-8);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

/* Booking widget wrapper — reserves space so the third-party widget never
   causes layout shift while its script loads/lazy-instantiates. */
.booking-widget-wrapper {
  min-height: 420px;
  background-color: var(--color-surface);
  border-radius: var(--radius-lg);
}

/* Experience cards — the homepage's visual centerpiece, not a generic card
   grid: portrait imagery that zooms subtly on hover, a floating price
   badge, confident large-numeral price type, elevate-on-hover with a
   tinted shadow. Mobile: horizontal scroll-snap carousel; desktop:
   three-column grid — one shared container, no duplicate markup between
   breakpoints. */
.experience-cards {
  display: flex;
  gap: var(--space-6);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding: var(--space-2) var(--space-1) var(--space-6);
}

@media (min-width: 900px) {
  .experience-cards {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    overflow-x: visible;
  }
}

.experience-card {
  flex: 0 0 85%;
  scroll-snap-align: center;
  display: flex;
  flex-direction: column;
  background-color: var(--color-white);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: transform var(--transition-standard) var(--ease-premium), box-shadow var(--transition-standard) var(--ease-premium);
}

@media (min-width: 900px) {
  .experience-card {
    flex: initial;
  }
}

.experience-card:hover,
.experience-card:focus-within {
  transform: translateY(-8px);
  box-shadow: var(--shadow-lg);
}

.experience-card__image-wrapper {
  position: relative;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  /* Subtle angled bottom edge — the same polygonal motif as the hero
     image, so the two sections read as one designed system. */
  clip-path: polygon(0 0, 100% 0, 100% 92%, 0 100%);
}

.experience-card__image-wrapper img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--transition-slow) var(--ease-premium);
  will-change: transform;
}

.experience-card:hover .experience-card__image-wrapper img,
.experience-card:focus-within .experience-card__image-wrapper img {
  transform: scale(1.09);
}

.experience-card__image-wrapper::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(30, 30, 30, 0) 55%, rgba(30, 30, 30, 0.55) 100%);
  pointer-events: none;
}

.experience-card__badge {
  position: absolute;
  top: var(--space-4);
  left: var(--space-4);
  z-index: 1;
  background-color: var(--color-primary);
  color: var(--color-white);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-sm);
}

.experience-card__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6);
}

.experience-card__name {
  margin: 0;
  font-size: var(--fs-400);
}

.experience-card__price {
  font-family: var(--font-display);
  font-size: var(--fs-600);
  font-weight: 700;
  color: var(--color-primary);
  line-height: 1;
}

.experience-card__price small {
  font-family: var(--font-body);
  font-size: var(--fs-100);
  font-weight: 500;
  color: var(--color-text-muted);
}

.experience-card__features {
  color: var(--color-text-muted);
  font-size: var(--fs-100);
}

.experience-card__cta {
  width: 100%;
  margin-top: auto;
}

/* Breadcrumbs */
.breadcrumbs__list {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: 0;
  margin: 0;
  font-size: var(--fs-100);
  color: var(--color-text-muted);
}

.breadcrumbs__list a {
  color: var(--color-text-muted);
}

.breadcrumbs__list a:hover {
  color: var(--color-primary);
}

/* On a dark hero/page-header, the default muted-grey breadcrumb text is
   invisible — lighten it contextually rather than adding a markup variant. */
.hero-cinematic .breadcrumbs,
.page-header .breadcrumbs {
  margin-bottom: var(--space-6);
}

.page-header .breadcrumbs__list {
  justify-content: center;
}

.hero-cinematic .breadcrumbs__list,
.hero-cinematic .breadcrumbs__list a,
.page-header .breadcrumbs__list,
.page-header .breadcrumbs__list a {
  color: rgba(255, 255, 255, 0.65);
}

.hero-cinematic .breadcrumbs__list a:hover,
.page-header .breadcrumbs__list a:hover {
  color: var(--color-white);
}

/* FAQ accordion — smooth height + opacity transition via the CSS grid-rows
   technique (animating a 0fr -> 1fr track is interpolable, unlike height:
   auto), plus a rotating chevron. No JS height calculation needed. */
.faq-item {
  border-bottom: 1px solid var(--color-border);
}

.faq-item__question {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  text-align: left;
  background: none;
  border: none;
  padding: var(--space-5) 0;
  font-family: var(--font-display);
  font-size: var(--fs-300);
  font-weight: 600;
  cursor: pointer;
  color: var(--color-ink);
}

.faq-item__icon {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background-color: var(--color-surface);
  position: relative;
  transition: background-color var(--transition-standard) var(--ease-premium);
}

/* Chevron drawn from a rotated border-corner (classic CSS trick) — points
   down at rest, flips to point up when the panel opens. Pure transform,
   GPU-accelerated. */
.faq-item__icon::before {
  content: '';
  position: absolute;
  top: 42%;
  left: 50%;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--color-primary);
  border-bottom: 2px solid var(--color-primary);
  transform: translate(-50%, -50%) rotate(45deg);
  transition: transform var(--transition-standard) var(--ease-premium);
}

.faq-item__question[aria-expanded="true"] .faq-item__icon {
  background-color: var(--color-primary);
}

.faq-item__question[aria-expanded="true"] .faq-item__icon::before {
  border-color: var(--color-white);
  transform: translate(-50%, -35%) rotate(225deg);
}

.faq-item__answer {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows var(--transition-standard) var(--ease-premium), opacity var(--transition-fast) ease;
}

.faq-item__answer.is-open {
  grid-template-rows: 1fr;
  opacity: 1;
}

.faq-item__answer > div {
  overflow: hidden;
}

.faq-item__answer p {
  padding-bottom: var(--space-5);
  color: var(--color-text-muted);
  margin: 0;
}

/* Consent banner. On mobile it must stack above the sticky CTA bar, not
   overlap it — both are fixed/bottom:0, so on first visit (before a
   consent choice is made) they'd otherwise render on top of each other. */
.consent-banner {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: var(--z-consent-banner);
  background-color: var(--color-white);
  box-shadow: var(--shadow-lg);
  padding: var(--space-6);
}

@media (max-width: 899px) {
  .consent-banner {
    bottom: calc(var(--mobile-cta-height) + env(safe-area-inset-bottom, 0px));
  }
}

.consent-banner__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

/* Language switcher */
.language-switcher {
  display: flex;
  gap: var(--space-2);
}

.language-switcher a {
  color: inherit;
  text-decoration: none;
  opacity: 0.7;
  transition: opacity var(--transition-fast);
}

.language-switcher a:hover {
  opacity: 1;
}

.language-switcher a[aria-current="true"] {
  font-weight: 700;
  opacity: 1;
}

/* ==========================================================================
   Cinematic hero — full-bleed background photo, dark gradient overlay,
   large display type, the header floats transparently over the top of it
   (see .site-header). Used on the homepage and each experience page.
   ========================================================================== */
.hero-cinematic {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  isolation: isolate;
  color: var(--color-white);
  padding-block: var(--space-24) var(--space-16);
}

.hero-cinematic__media {
  position: absolute;
  inset: 0;
  z-index: -2;
  overflow: hidden;
}

.hero-cinematic__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  animation: hero-ken-burns 18s var(--ease-premium) infinite alternate;
  will-change: transform;
}

@keyframes hero-ken-burns {
  from { transform: scale(1); }
  to { transform: scale(1.08); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-cinematic__media img {
    animation: none;
  }
}

.hero-cinematic__overlay {
  position: absolute;
  inset: 0;
  z-index: -1;
  /* Horizontal reach checked against all 3 photos this component now
     renders (rental-30 subject ~54%, rental-60 subject ~44%, tabarca jet
     ski nose ~42% after mirroring) — fully transparent by 34% clears the
     tightest of those with a buffer, on every one of them, so this one
     shared gradient never needs a per-page override. */
  background:
    linear-gradient(180deg, rgba(20, 20, 22, 0.35) 0%, rgba(20, 20, 22, 0.35) 40%, rgba(15, 15, 17, 0.92) 100%),
    linear-gradient(90deg, rgba(15, 15, 17, 0.62) 0%, rgba(15, 15, 17, 0) 34%);
}

.hero-cinematic__content {
  position: relative;
  max-width: 780px;
}

/* Narrower than the base 780px specifically for the --compact variant (the
   only one any page actually uses). Measured directly against all 3
   photos this component renders: none of them are wide enough relative to
   this very short/wide hero band to allow horizontal repositioning via
   object-position — object-fit:cover keeps their full width regardless of
   anchor, so the subject's horizontal position is fixed by the source
   photo itself (as low as ~42-44% of viewport width on two of the three).
   A 780px-wide text column reaches well past that on any normal desktop
   viewport — paragraph lines were measured overlapping the jet ski
   directly. 560px keeps every line clear of the tightest case with a
   buffer, the gradient's job is then purely contrast, not exclusion. */
.hero-cinematic--compact .hero-cinematic__content {
  max-width: 560px;
}

.hero-cinematic__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-primary);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: var(--fs-100);
  margin-bottom: var(--space-4);
}

.hero-cinematic__eyebrow::before {
  content: '';
  width: 28px;
  height: 2px;
  background-color: var(--color-primary);
}

.hero-cinematic__content h1 {
  font-size: var(--fs-hero);
  color: var(--color-white);
  margin-bottom: var(--space-6);
  text-wrap: balance;
}

/* Every real page using this component uses the --compact variant (50-52vh,
   not the base 100vh) — --fs-hero (~99px desktop) was sized for a
   full-height hero, not this compact column. A 48-51 character headline at
   that size wrapped to 3-4 lines and, since min-height doesn't cap
   content, pushed the section (and the booking panel/CTA below it) well
   past the intended height — same root cause as the homepage hero bug,
   same fix: its own scale. Sized against the column's actual 560px width
   (.hero-cinematic__content max-width is overridden narrower below, to
   clear the jet ski in all 3 photos this component renders) so these
   headlines set in ~2 lines. */
.hero-cinematic--compact .hero-cinematic__content h1 {
  font-size: clamp(2rem, 1.5rem + 1.6vw, 2.75rem);
}

.hero-cinematic__content p {
  font-size: var(--fs-300);
  color: rgba(255, 255, 255, 0.82);
  max-width: 56ch;
  margin-bottom: var(--space-8);
}

.hero-cinematic__scroll-cue {
  position: absolute;
  bottom: var(--space-8);
  left: 50%;
  transform: translateX(-50%);
  width: 26px;
  height: 42px;
  border: 2px solid rgba(255, 255, 255, 0.5);
  border-radius: 100px;
  display: none;
}

@media (min-width: 900px) {
  .hero-cinematic__scroll-cue {
    display: block;
  }
}

.hero-cinematic__scroll-cue::before {
  content: '';
  position: absolute;
  top: 8px;
  left: 50%;
  width: 4px;
  height: 8px;
  background-color: var(--color-white);
  border-radius: 4px;
  transform: translateX(-50%);
  animation: scroll-cue-drop 1.8s ease infinite;
}

@keyframes scroll-cue-drop {
  0% { opacity: 1; top: 8px; }
  70% { opacity: 0; top: 20px; }
  100% { opacity: 0; top: 8px; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-cinematic__scroll-cue::before {
    animation: none;
  }
}

/* Deliberately no opacity:0/entrance-animation gate here either — see the
   matching note by .hero-split__content-inner. Hero copy (booking panel's
   whole reason for existing on these pages) must never depend on an
   animation completing to become visible. */

/* Pricing highlight — the one number a visitor needs before they'll even
   consider the CTA. Glass chip, not a full card, so it reads as part of
   the hero's own composition rather than a bolted-on component. */
.hero-cinematic__price-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  background: rgba(237, 42, 145, 0.14);
  border: 1px solid rgba(237, 42, 145, 0.5);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  padding: var(--space-3) var(--space-6);
  border-radius: 100px;
  margin-bottom: var(--space-8);
  box-shadow: 0 4px 24px rgba(237, 42, 145, 0.18);
}

.hero-cinematic__price-badge .price-badge__value {
  font-family: var(--font-display);
  font-size: var(--fs-500);
  font-weight: 700;
  color: var(--color-white);
  line-height: 1;
}

.hero-cinematic__price-badge .price-badge__label {
  color: rgba(255, 255, 255, 0.75);
  font-size: var(--fs-100);
  border-left: 1px solid rgba(255, 255, 255, 0.28);
  padding-left: var(--space-3);
}

/* Compact hero — the 3 experience pages (30/60/Tabarca) plus precios.php
   and contacto.php. Short by design: the booking panel is the point of
   these pages, and it must sit inside the first viewport on desktop, not
   below a tall photo. 48-55vh across breakpoints, never taller. */
.hero-cinematic--compact {
  min-height: 50vh;
  min-height: 50svh;
  padding-block: var(--space-24) var(--space-12);
}

@media (min-width: 900px) {
  .hero-cinematic--compact {
    min-height: 52vh;
    min-height: 52svh;
  }
}

/* ==========================================================================
   Homepage hero — .hero-split. A premium landing-page hero, not a
   fullscreen photograph: a left content zone (headline, trust, CTAs) that
   visually dominates, with the photograph supporting it on the right.
   Never 100vh. On desktop this is a true visual 40/60 split, achieved via
   a wide, mostly-solid gradient over a full-bleed image rather than real
   CSS columns — the same DOM structure works at every breakpoint, and it
   means the "split" can collapse cleanly to a stacked photo-then-content
   layout on mobile without a second markup pattern. The right ~55-60% of
   the image is left essentially undarkened at every breakpoint — the
   Mediterranean stays vibrant, per brief.
   ========================================================================== */
.hero-split {
  position: relative;
  min-height: 55vh;
  min-height: 55svh;
  display: flex;
  flex-direction: column;
  background-color: var(--color-ink);
  overflow: hidden;
  isolation: isolate;
}

@media (min-width: 600px) {
  .hero-split {
    min-height: 60vh;
    min-height: 60svh;
  }
}

@media (min-width: 900px) {
  .hero-split {
    min-height: 65vh;
    min-height: 65svh;
    display: block;
  }
}

/* Mobile/tablet: image is a fixed-height band at the top of the stack.
   min-width:0 matters here specifically: this is a flex item (.hero-split
   is display:flex on mobile/tablet) containing a replaced element (<img>)
   with a ~1.9:1 intrinsic aspect ratio. Without min-width:0, that
   aspect-ratio-derived intrinsic size (height × 1.9 ≈ 580px at this band's
   actual height) can be used as the flex item's automatic minimum width,
   silently forcing the whole flex column — and every sibling that
   stretches to match it — wider than the real 390px viewport. This was the
   actual root cause of the hero text clipping, not the content column. */
.hero-split__media {
  position: relative;
  height: 34vh;
  min-height: 220px;
  min-width: 0;
  overflow: hidden;
}

@media (min-width: 600px) {
  .hero-split__media {
    height: 38vh;
  }
}

/* Desktop: image becomes the full-bleed backdrop for the whole section. */
@media (min-width: 900px) {
  .hero-split__media {
    position: absolute;
    inset: 0;
    height: auto;
    z-index: 0;
  }
}

.hero-split__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Slow, subtle zoom — reinforces motion/quality without being decorative
     for its own sake (the water spray in the photo already implies
     movement; this just keeps the frame from feeling static). */
  animation: hero-split-zoom 22s var(--ease-premium) infinite alternate;
}

@keyframes hero-split-zoom {
  from { transform: scale(1); }
  to { transform: scale(1.06); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-split__media img {
    animation: none;
  }
}

/* Scrim — mobile/tablet: a short fade where the image band meets the solid
   content panel below it, so the seam reads as one composition. */
.hero-split__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgba(10, 10, 12, 0) 55%, rgba(10, 10, 12, 0.85) 100%);
}

@media (min-width: 900px) {
  .hero-split__scrim {
    /* Verified against the actual hero photo (not guessed — measured the
       rider's pixel position directly): at this image's object-fit:cover
       crop, the jet ski/rider sits at ~38% from the left. The strong
       left-side gradient below is fully transparent by 30%, leaving a
       clear buffer so it never touches the subject. This photo also has an
       intense sun-glare/foam highlight that runs much wider than the
       subject and washes out white text on its own — a second, uniform
       22% black wash across the whole frame tames that without reading as
       "a dark overlay": the water stays clearly turquoise and the glare
       still clearly reads as sunlit, just no longer bright enough to fight
       the text sitting over it. */
    background:
      linear-gradient(
        90deg,
        var(--color-ink) 0%,
        var(--color-ink) 12%,
        rgba(20, 20, 22, 0.7) 18%,
        rgba(20, 20, 22, 0.35) 23%,
        rgba(20, 20, 22, 0.1) 27%,
        rgba(20, 20, 22, 0) 30%
      ),
      rgba(8, 8, 10, 0.22);
  }
}

.hero-split__content {
  position: relative;
  z-index: 2;
  /* min-width:0 overrides the flex-item default of min-width:auto, which
     otherwise sizes this box to its content's unwrapped min-content width
     instead of letting it shrink to the column's actual width — the
     classic flexbox text-overflow trap (.hero-split is display:flex on
     mobile/tablet). Without this, long trust-row/paragraph text pushed the
     box wider than the viewport and got silently clipped instead of
     wrapping. */
  min-width: 0;
  background-color: var(--color-ink);
  color: var(--color-white);
  padding-block: var(--space-8) var(--space-12);
}

@media (min-width: 900px) {
  .hero-split__content {
    background-color: transparent;
    min-height: 65vh;
    min-height: 65svh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-block: calc(var(--header-height) + var(--space-4)) var(--space-6);
  }
}

.hero-split__content-inner {
  max-width: 620px;
}

.hero-split .hero-cinematic__eyebrow {
  margin-bottom: var(--space-4);
}

/* Deliberately its own scale, not --fs-hero (that token is tuned for a
   full-width centered hero). This column tops out at 620px — at
   --fs-hero's ~99px desktop size, a 5-word headline wrapped to 4 lines and
   pushed the CTAs and price badge off-screen entirely. Sized so "Alquiler
   de motos de agua / en Alicante" sets in exactly two lines at the column
   width. */
.hero-split h1 {
  font-size: clamp(2.25rem, 1.5rem + 2.6vw, 3.25rem);
  color: var(--color-white);
  margin-bottom: var(--space-5);
  text-wrap: balance;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.55), 0 1px 28px rgba(0, 0, 0, 0.5);
}

.hero-split__content-inner > p:not([class]) {
  font-size: 1.0625rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.92);
  margin-bottom: var(--space-4);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.5), 0 1px 20px rgba(0, 0, 0, 0.4);
}

.hero-split .btn-group {
  margin-bottom: var(--space-4);
}

.hero-split .hero-cinematic__price-badge {
  margin-bottom: 0;
}

/* Deliberately NO opacity:0/entrance-animation gate on hero content. This
   is the single most important content on the page — it must be visible
   on first paint, unconditionally, with zero dependency on an animation
   engine actually completing. (A prior version staggered these children in
   via an opacity:0 + keyframe animation; if that animation ever failed to
   fire — slow devices, automated rendering, a future typo in the keyframe
   name — the entire hero silently went blank. Not worth the risk for a
   commercial hero whose whole job is to be readable in the first 5
   seconds.) */

/* Trust row — sales arguments, not decoration: rating, review count, fleet
   size, and the three biggest objection-killers, as compact chips that
   wrap naturally. Shared class (not hero-split-specific) so any future
   hero can reuse it. */
.hero-trust {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-5);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid rgba(255, 255, 255, 0.18);
  /* text-shadow inherits to every child (rating, items) — same legibility
     insurance as the h1/paragraph above, needed because this row can sit
     over the photo's bright sun-glare on wide viewports. */
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.5), 0 1px 20px rgba(0, 0, 0, 0.4);
}

.hero-trust__rating {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 700;
  color: var(--color-white);
}

.hero-trust__rating .trust-stars {
  color: var(--color-primary);
  letter-spacing: 0.08em;
  font-size: var(--fs-200);
  line-height: 1;
}

.hero-trust__rating .trust-count {
  color: rgba(255, 255, 255, 0.68);
  font-weight: 500;
  font-size: var(--fs-100);
}

.hero-trust__item {
  color: rgba(255, 255, 255, 0.85);
  font-size: var(--fs-100);
  font-weight: 600;
  position: relative;
  padding-left: var(--space-4);
}

.hero-trust__item::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background-color: var(--color-primary);
}

/* Non-hero page intro band — precios/contacto/legal pages. Dark, branded,
   consistent with the hero's palette so no page feels like a different
   site, without the full cinematic height (would be excessive for a
   utility page). */
.page-header {
  position: relative;
  background-color: var(--color-ink);
  color: var(--color-white);
  text-align: center;
  padding-block: var(--space-24) var(--space-16);
  overflow: hidden;
  isolation: isolate;
}

.page-header::before {
  content: '';
  position: absolute;
  top: -30%;
  right: -10%;
  width: 60%;
  aspect-ratio: 1;
  background: radial-gradient(circle, rgba(237, 42, 145, 0.35) 0%, rgba(237, 42, 145, 0) 70%);
  z-index: -1;
}

.page-header h1 {
  color: var(--color-white);
  margin-bottom: var(--space-4);
}

.page-header p {
  color: rgba(255, 255, 255, 0.75);
  max-width: 640px;
  margin-inline: auto;
  font-size: var(--fs-300);
}

/* Icon strip — compact, horizontally scrollable on mobile, evenly spaced
   on desktop. Used for the intro strip (sin licencia / location / duration). */
.icon-strip {
  display: flex;
  gap: var(--space-6);
  overflow-x: auto;
  padding-block: var(--space-5);
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

@media (min-width: 900px) {
  .icon-strip {
    justify-content: center;
    overflow-x: visible;
  }
}

.icon-strip__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  white-space: nowrap;
  font-size: var(--fs-200);
  font-weight: 500;
}

/* Same premium circular-badge treatment as .feature-card__icon, sized to
   this component's own scale (a dense single-line strip, not a card grid —
   64px badges here would double the strip's height and fight its ticker
   role). Consistent stroke/weight/palette either way. */
.icon-strip__item-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, rgba(237, 42, 145, 0.14), rgba(237, 42, 145, 0.04) 70%);
}

.icon-strip__item img {
  width: 22px;
  height: 22px;
  filter: invert(13%) sepia(64%) saturate(6577%) hue-rotate(316deg) brightness(89%) contrast(93%);
}

/* ==========================================================================
   Feature grid — "what's included" sections (homepage, precios.php, each
   experience page). Replaces the old plain icon+text columns: this is a
   card grid, designed to raise perceived value, not a documentation list.
   4 columns desktop / 2 tablet / 1 mobile, every card the same height
   (grid's default row-stretch + height:100% on the card — content length
   differences never produce a taller first card).
   ========================================================================== */
/* margin-bottom intentionally matches the global h2 rule (base.css) exactly
   — a bare <h2> and a <h2>+subtitle .section-heading must leave the same
   gap before whatever content follows, so heading spacing reads as one
   standard regardless of which pattern a given section uses. */
.section-heading {
  max-width: 620px;
  margin-inline: auto;
  margin-bottom: var(--space-6);
  text-align: center;
}

@media (min-width: 900px) {
  .section-heading {
    margin-bottom: var(--space-8);
  }
}

.section-heading__subtitle {
  color: var(--color-text-muted);
  font-size: var(--fs-300);
  margin: 0;
}

.feature-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: stretch;
}

@media (min-width: 600px) {
  .feature-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 900px) {
  .feature-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

.feature-card {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  gap: var(--space-3);
  background:
    radial-gradient(circle at 85% -10%, rgba(237, 42, 145, 0.08) 0%, rgba(237, 42, 145, 0) 55%),
    linear-gradient(165deg, #ffffff 0%, var(--color-surface) 130%);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-8) var(--space-6) var(--space-6);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-standard) var(--ease-premium), box-shadow var(--transition-standard) var(--ease-premium), border-color var(--transition-standard) var(--ease-premium);
}

.feature-card:hover,
.feature-card:focus-within {
  transform: translateY(-6px);
  box-shadow: var(--shadow-lg);
  border-color: rgba(237, 42, 145, 0.3);
}

.feature-card__icon {
  width: 72px;
  height: 72px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, rgba(237, 42, 145, 0.16), rgba(237, 42, 145, 0.05) 70%);
  margin-bottom: var(--space-1);
  transition: transform var(--transition-standard) var(--ease-premium);
}

.feature-card:hover .feature-card__icon {
  transform: scale(1.08) rotate(-4deg);
}

.feature-card__icon img {
  width: 32px;
  height: 32px;
  filter: invert(13%) sepia(64%) saturate(6577%) hue-rotate(316deg) brightness(89%) contrast(93%);
}

.feature-card__title {
  font-size: var(--fs-400);
  margin: 0;
  line-height: var(--lh-tight);
}

.feature-card__text {
  color: var(--color-text-muted);
  font-size: var(--fs-100);
  line-height: 1.5;
  margin: 0;
}

/* CTA banner — reusable dark band, used for both the mid-page and final
   closing CTAs. */
.cta-banner {
  position: relative;
  background-color: var(--color-ink);
  color: var(--color-white);
  text-align: center;
  padding-block: var(--space-12);
  overflow: hidden;
  isolation: isolate;
}

.cta-banner::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% 0%, rgba(237, 42, 145, 0.22) 0%, rgba(237, 42, 145, 0) 60%);
  z-index: -1;
}

.cta-banner a {
  color: var(--color-white);
}

/* Two-column narrative layout — reusable for Fleet & Equipment and any
   future "photo + text" section. */
.narrative {
  display: grid;
  gap: var(--space-8);
}

@media (min-width: 900px) {
  .narrative {
    grid-template-columns: 1fr 1fr;
    align-items: center;
    gap: var(--space-16);
  }
}

.narrative img {
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.narrative__list {
  list-style: none;
  margin: var(--space-6) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.narrative__list li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  color: var(--color-text-muted);
}

.narrative__list img {
  flex-shrink: 0;
  border-radius: 0;
  box-shadow: none;
  margin-top: 2px;
}

/* Contact grid — map + details, reused wherever location content appears. */
.contact-grid {
  display: grid;
  gap: var(--space-6);
}

@media (min-width: 900px) {
  .contact-grid {
    grid-template-columns: 60fr 40fr;
  }
}

.contact-grid__location-label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-300);
  margin-bottom: var(--space-2);
}

.contact-grid__map {
  min-height: 320px;
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}

.contact-grid__map iframe {
  width: 100%;
  height: 100%;
  min-height: 320px;
  border: 0;
  display: block;
}

@media (min-width: 900px) {
  .contact-grid__map {
    min-height: 100%;
  }
}

/* Gallery carousel — scroll-position-based, not a transform reimplementation,
   so touch devices get native momentum scrolling. Media-agnostic:
   .gallery-carousel__item can hold <img> today or <video> later with no
   CSS change (see docs/component-contracts.md). Clicking an item opens the
   lightbox (assets/js/lightbox.js). */
.gallery-carousel {
  position: relative;
}

.gallery-carousel__track {
  display: flex;
  gap: var(--space-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  list-style: none;
  margin: 0;
  padding: var(--space-2) var(--space-1) var(--space-2);
}

.gallery-carousel__item {
  flex: 0 0 85%;
  scroll-snap-align: center;
  border-radius: var(--radius-lg);
  overflow: hidden;
  position: relative;
}

@media (min-width: 900px) {
  .gallery-carousel__item {
    flex-basis: 31%;
  }
}

.gallery-carousel__item button {
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: none;
  background: none;
  cursor: zoom-in;
  aspect-ratio: 4 / 3;
}

.gallery-carousel__item img,
.gallery-carousel__item video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--transition-slow) var(--ease-premium);
}

.gallery-carousel__item:hover img {
  transform: scale(1.06);
}

.gallery-carousel [data-carousel-prev],
.gallery-carousel [data-carousel-next] {
  display: none;
}

@media (min-width: 900px) {
  .gallery-carousel [data-carousel-prev],
  .gallery-carousel [data-carousel-next] {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 48px;
    height: 48px;
    border-radius: 50%;
    border: none;
    background-color: var(--color-white);
    box-shadow: var(--shadow-lg);
    cursor: pointer;
    z-index: 1;
    transition: transform var(--transition-fast), background-color var(--transition-fast);
  }

  .gallery-carousel [data-carousel-prev]:hover,
  .gallery-carousel [data-carousel-next]:hover {
    background-color: var(--color-primary);
    color: var(--color-white);
    transform: translateY(-50%) scale(1.08);
  }

  .gallery-carousel [data-carousel-prev] { left: var(--space-2); }
  .gallery-carousel [data-carousel-next] { right: var(--space-2); }
}

.gallery-carousel__dots {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

.gallery-carousel__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: none;
  padding: 0;
  background-color: var(--color-border);
  cursor: pointer;
  transition: background-color var(--transition-fast), transform var(--transition-fast);
}

.gallery-carousel__dot[aria-current="true"] {
  background-color: var(--color-primary);
  transform: scale(1.3);
}

/* Lightbox — opens on gallery item click. Video-ready: swaps in whatever
   media type the triggering .gallery-carousel__item holds. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-lightbox);
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(15, 15, 17, 0.94);
  padding: var(--space-6);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--transition-standard) ease, visibility 0s linear var(--transition-standard);
}

.lightbox[data-open="true"] {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--transition-standard) ease;
}

.lightbox__figure {
  max-width: min(1100px, 92vw);
  max-height: 86vh;
  transform: scale(0.96);
  transition: transform var(--transition-standard) var(--ease-premium);
}

.lightbox[data-open="true"] .lightbox__figure {
  transform: scale(1);
}

.lightbox__figure img {
  max-width: 100%;
  max-height: 86vh;
  width: auto;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}

.lightbox__close,
.lightbox__prev,
.lightbox__next {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: none;
  background-color: rgba(255, 255, 255, 0.12);
  color: var(--color-white);
  cursor: pointer;
  transition: background-color var(--transition-fast), transform var(--transition-fast);
}

.lightbox__close:hover,
.lightbox__prev:hover,
.lightbox__next:hover {
  background-color: var(--color-primary);
}

.lightbox__close {
  top: var(--space-6);
  right: var(--space-6);
}

.lightbox__prev,
.lightbox__next {
  top: 50%;
  transform: translateY(-50%);
}

.lightbox__prev:hover,
.lightbox__next:hover {
  transform: translateY(-50%) scale(1.08);
}

.lightbox__prev { left: var(--space-4); }
.lightbox__next { right: var(--space-4); }

@media (max-width: 599px) {
  .lightbox__prev, .lightbox__next { display: none; }
}

/* ==========================================================================
   Scroll reveal — IntersectionObserver-driven (assets/js/scroll-reveal.js)
   fade/slide-up, GPU-only properties (opacity/transform). Staggered
   children via --reveal-delay, set inline per item. One-time (unobserved
   after first reveal), inert entirely under prefers-reduced-motion via the
   global override in base.css.
   ========================================================================== */
[data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity var(--transition-slow) var(--ease-premium), transform var(--transition-slow) var(--ease-premium);
  transition-delay: var(--reveal-delay, 0ms);
}

[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Pricing cards — same visual language as .experience-card (rounded,
   shadow, hover lift) but no image: price/duration is the visual anchor
   instead of a photo. Used on precios.php and as the summary block
   repeated on each experience page. */
.pricing-cards {
  display: grid;
  gap: var(--space-6);
}

@media (min-width: 600px) {
  .pricing-cards {
    grid-template-columns: repeat(3, 1fr);
  }
}

.pricing-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  background-color: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
  padding: var(--space-8) var(--space-6) var(--space-6);
  transition: transform var(--transition-standard) var(--ease-premium), box-shadow var(--transition-standard) var(--ease-premium);
}

.pricing-card:hover,
.pricing-card:focus-within {
  transform: translateY(-6px);
  box-shadow: var(--shadow-lg);
}

.pricing-card--featured {
  border-color: var(--color-primary);
  border-width: 2px;
}

.pricing-card--featured::before {
  content: 'Más popular';
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: var(--color-primary);
  color: var(--color-white);
  font-size: var(--fs-100);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: var(--space-1) var(--space-4);
  border-radius: 100px;
  white-space: nowrap;
}

.pricing-card__duration {
  margin: 0;
  font-size: var(--fs-400);
}

.pricing-card__price {
  font-family: var(--font-display);
  font-size: var(--fs-600);
  font-weight: 700;
  color: var(--color-primary);
  margin: 0;
}

.pricing-card__price small {
  font-family: var(--font-body);
  font-size: var(--fs-100);
  font-weight: 400;
  color: var(--color-text-muted);
}

.pricing-card__cta {
  width: 100%;
  margin-top: auto;
}

/* Feature list — icon + text rows, used on experience pages ("qué incluye")
   and pricing cards alike. Reuses .icon-grid__item's icon sizing idiom but
   as a left-aligned row list rather than a centered grid. */
.feature-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
}

.feature-list__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.feature-list__item img {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
}

/* Trust stat strip — social proof band (real aggregate figures, sourced
   from the same operating business, PROJECT.md §12). */
.stat-strip {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-8);
  text-align: center;
  max-width: 720px;
  margin-inline: auto;
}

@media (min-width: 600px) {
  .stat-strip {
    grid-template-columns: repeat(3, 1fr);
  }
}

.stat-strip__number {
  font-family: var(--font-display);
  font-size: var(--fs-600);
  font-weight: 700;
  color: var(--color-primary);
  line-height: 1;
  margin-bottom: var(--space-2);
}

.stat-strip__label {
  color: var(--color-text-muted);
  font-size: var(--fs-100);
}

/* Booking panel — merges the price/features summary and the Nautisync
   widget into one designed object instead of two separately-floating
   pieces stacked on the page. This is the page's single pricing moment,
   positioned immediately before the widget it belongs to. */
.booking-panel {
  display: grid;
  gap: var(--space-8);
  background-color: var(--color-white);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--color-border);
  padding: var(--space-8);
}

@media (min-width: 900px) {
  .booking-panel {
    grid-template-columns: 34fr 66fr;
    gap: var(--space-12);
    padding: var(--space-12);
  }
}

.booking-panel__price {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

@media (min-width: 900px) {
  .booking-panel__price {
    padding-inline-end: var(--space-12);
    border-inline-end: 1px solid var(--color-border);
  }
}

.booking-panel__duration {
  color: var(--color-text-muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: var(--fs-100);
  margin: 0;
}

.booking-panel__price-value {
  font-family: var(--font-display);
  font-size: var(--fs-700);
  font-weight: 700;
  color: var(--color-primary);
  line-height: 1;
  margin: 0;
}

.booking-panel__price-value small {
  display: block;
  font-family: var(--font-body);
  font-size: var(--fs-100);
  font-weight: 500;
  color: var(--color-text-muted);
  margin-top: var(--space-2);
}

.booking-panel .booking-widget-wrapper {
  min-height: 460px;
}

/* Contact form */
.contact-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: 640px;
  margin-inline: auto;
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.form-field label {
  font-weight: 600;
  font-size: var(--fs-100);
}

.form-field input,
.form-field textarea {
  font-family: var(--font-body);
  font-size: var(--fs-200);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  min-height: 48px;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form-field input:hover,
.form-field textarea:hover {
  border-color: var(--color-mid-gray);
}

.form-field textarea {
  min-height: 140px;
  resize: vertical;
}

.form-field input:focus-visible,
.form-field textarea:focus-visible {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 4px rgba(237, 42, 145, 0.14);
}

.form-field--error input,
.form-field--error textarea {
  border-color: var(--color-primary);
}

.form-field__error {
  color: var(--color-primary);
  font-size: var(--fs-100);
}

/* Honeypot field — must stay visually and programmatically hidden from
   real users while remaining in the tab/DOM order bots crawl (see
   forms/contact-handler.php). Never `display:none`, which some bots skip. */
.form-field--honeypot {
  position: absolute !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

.form-status {
  padding: var(--space-4);
  border-radius: var(--radius-md);
  font-weight: 600;
}

.form-status[hidden] {
  display: none;
}

.form-status--success {
  background-color: var(--color-surface);
  color: var(--color-ink);
  border: 1px solid var(--color-primary);
}

.form-status--error {
  background-color: var(--color-surface);
  color: var(--color-primary);
  border: 1px solid var(--color-primary);
}

/* Legal prose — privacy/legal-notice/cookies pages. Plain, readable
   long-form content; deliberately not a generic ".prose" reset since this
   project has no other long-form content type yet. */
.legal-content {
  max-width: 760px;
}

.legal-content h2 {
  font-size: var(--fs-500);
  margin-top: var(--space-12);
}

.legal-content h3 {
  font-size: var(--fs-400);
  margin-top: var(--space-8);
}

.legal-content ul,
.legal-content ol {
  padding-left: var(--space-6);
  margin: 0 0 var(--space-4);
}

.legal-content li {
  margin-bottom: var(--space-2);
}

.legal-content__updated {
  color: var(--color-text-muted);
  font-size: var(--fs-100);
}

.legal-content table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 var(--space-6);
  font-size: var(--fs-100);
}

.legal-content th,
.legal-content td {
  text-align: left;
  padding: var(--space-3);
  border-bottom: 1px solid var(--color-border);
}
