/* ==========================================================================
   Holiday Photo Tenerife — Global Stylesheet
   Phase 1 scaffold: design tokens + global components + homepage skeleton
   ========================================================================== */

/* ---------------------------------------------------------------------- */
/* Design tokens                                                          */
/* ---------------------------------------------------------------------- */
:root {
  /* Colors — from BUILD_SPEC.md section 1 */
  --color-bg-base: #181818;
  --color-bg-surface: #1f1f1f;
  --color-bg-elevated: #262626;
  --color-accent-gold: #C8903A;
  --color-accent-gold-soft: #DDAE6B;
  --color-ocean-blue: #4A8FAD;
  --color-sand-brown: #A07850;
  --color-text-main: #F0EBE3;
  --color-text-muted: rgba(240, 235, 227, 0.72);
  --color-text-faint: rgba(240, 235, 227, 0.5);
  --color-border: rgba(240, 235, 227, 0.14);
  --color-overlay: rgba(10, 10, 10, 0.55);
  --color-overlay-strong: rgba(8, 8, 8, 0.72);

  /* Typography */
  --font-heading: 'DM Serif Display', Georgia, serif;
  --font-body: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;

  --fs-h1: clamp(2.5rem, 5vw + 1rem, 4.75rem);
  --fs-h2: clamp(2rem, 3vw + 1rem, 3rem);
  --fs-h3: clamp(1.35rem, 1.5vw + 1rem, 1.75rem);
  --fs-lead: clamp(1.05rem, 0.5vw + 1rem, 1.25rem);
  --fs-body: 1rem;
  --fs-small: 0.875rem;

  /* Spacing scale */
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs: 0.75rem;
  --space-sm: 1rem;
  --space-md: 1.5rem;
  --space-lg: 2.5rem;
  --space-xl: 4rem;
  --space-2xl: 6rem;

  /* Layout */
  --container-max: 1220px;
  --container-pad: 1.25rem;
  --header-height: 76px;
  --mobile-cta-height: 68px;
  --whatsapp-size: 56px;

  /* Motion */
  --transition-fast: 0.2s ease;
  --transition-base: 0.35s ease;

  /* Z-index scale — header stays above the mobile nav overlay so its
     toggle button remains clickable (to close the menu) while open */
  --z-mobile-cta: 140;
  --z-whatsapp: 150;
  --z-mobile-nav: 200;
  --z-header: 210;
  --z-lightbox: 300;
  --z-cookie-banner: 400;
}

/* ---------------------------------------------------------------------- */
/* Reset                                                                  */
/* ---------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--color-bg-base);
  color: var(--color-text-main);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, p, figure, ul, ol {
  margin: 0;
}

ul, ol {
  padding: 0;
  list-style: none;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 400;
  line-height: 1.15;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}

:focus-visible {
  outline: 2px solid var(--color-accent-gold);
  outline-offset: 3px;
}

/* ---------------------------------------------------------------------- */
/* Layout utilities                                                       */
/* ---------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}

.section {
  padding-block: var(--space-2xl);
}

.section-title {
  font-size: var(--fs-h2);
  text-align: center;
  margin-bottom: var(--space-lg);
}

.section-cta {
  display: flex;
  justify-content: center;
  margin-top: var(--space-lg);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.is-hidden {
  display: none !important;
}

/* ---------------------------------------------------------------------- */
/* Buttons                                                                */
/* ---------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  padding: 0.9rem 1.85rem;
  border-radius: 999px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
  border: 1px solid transparent;
  white-space: nowrap;
  transition: background-color var(--transition-fast), border-color var(--transition-fast),
    color var(--transition-fast), transform var(--transition-fast);
}

.btn-primary {
  background: var(--color-accent-gold);
  border-color: var(--color-accent-gold);
  color: #181818;
}

.btn-primary:hover {
  background: var(--color-accent-gold-soft);
  border-color: var(--color-accent-gold-soft);
  transform: translateY(-1px);
}

.btn-outline {
  background: transparent;
  border-color: rgba(240, 235, 227, 0.4);
  color: var(--color-text-main);
}

.btn-outline:hover {
  border-color: var(--color-text-main);
  background: rgba(240, 235, 227, 0.08);
}

/* WhatsApp brand green — used only on the mobile sticky CTA bar's WhatsApp
   button (its own visual accent now that the floating WhatsApp bubble is
   desktop-only, see .whatsapp-float below) */
.btn-whatsapp {
  background: #25D366;
  border-color: #25D366;
  color: #0b0b0b;
}

.btn-whatsapp:hover {
  background: #2fe077;
  border-color: #2fe077;
  transform: translateY(-1px);
}

.btn-sm {
  padding: 0.6rem 1.4rem;
  font-size: 0.85rem;
}

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3xs);
  font-weight: 700;
  font-size: var(--fs-small);
  color: var(--color-accent-gold);
  border-bottom: 1px solid transparent;
  transition: border-color var(--transition-fast);
}

.link-arrow:hover {
  border-color: var(--color-accent-gold);
}

.badge {
  display: inline-block;
  padding: 0.3rem 0.9rem;
  border-radius: 999px;
  background: var(--color-accent-gold);
  color: #181818;
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* ==========================================================================
   Global components
   ========================================================================== */

/* ---------------------------------------------------------------------- */
/* Header / primary navigation                                            */
/* ---------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  height: var(--header-height);
  display: flex;
  align-items: center;
  background: rgba(24, 24, 24, 0.75);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid transparent;
  transition: background-color var(--transition-base), border-color var(--transition-base);
}

.site-header.is-scrolled {
  background: rgba(24, 24, 24, 0.92);
  border-bottom-color: var(--color-border);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
}

.logo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
}

.logo img {
  height: 38px;
  width: auto;
  display: block;
  flex: none;
}

/* Real text, not baked into the logo image — the old single-image lockup
   (icon + 2-line wordmark) had a ~3:1 aspect ratio, so forcing it to a
   header-friendly height shrank the text to an illegible ~120px width.
   Splitting the icon from the wordmark lets the text render crisp at any
   size, in the site's own fonts — including the domain line, which the
   flattened image could never keep legible at header height either. */
.logo__text-group {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}

.logo__text {
  font-family: var(--font-heading);
  font-size: 1.1rem;
  line-height: 1;
  color: var(--color-text-main);
  white-space: nowrap;
}

.logo__domain {
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  white-space: nowrap;
  margin-top: 0.2rem;
}

.logo__domain-accent {
  color: var(--color-accent-gold);
}

.site-nav {
  display: none;
}

.site-nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  font-size: 1rem;
  font-weight: 500;
}

.site-nav__list a {
  transition: color var(--transition-fast);
}

.site-nav__list a:hover {
  color: var(--color-accent-gold);
}

.site-nav__list a[aria-current='page'],
.mobile-nav__list a[aria-current='page'] {
  color: var(--color-accent-gold);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 6px;
  text-decoration-thickness: 2px;
}

.site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

/* Language switcher (used in header + footer) */
.lang-switcher {
  position: relative;
}

.lang-switcher__toggle {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 0.4rem 0.2rem;
}

.lang-switcher__toggle::after {
  content: '';
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  transition: transform var(--transition-fast);
}

.lang-switcher.is-open .lang-switcher__toggle::after {
  transform: rotate(180deg);
}

.lang-switcher__menu {
  position: absolute;
  top: calc(100% + 0.6rem);
  right: 0;
  min-width: 150px;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  padding: 0.4rem;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity var(--transition-fast), transform var(--transition-fast), visibility var(--transition-fast);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35);
}

.lang-switcher.is-open .lang-switcher__menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.lang-switcher__menu a {
  display: block;
  padding: 0.55rem 0.75rem;
  border-radius: 6px;
  font-size: 0.9rem;
}

.lang-switcher__menu a:hover {
  background: rgba(240, 235, 227, 0.08);
}

.lang-switcher__menu a[aria-current='true'] {
  color: var(--color-accent-gold);
}

.site-header__cta {
  display: none;
}

/* Hamburger toggle */
.nav-toggle {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 32px;
  height: 32px;
}

.nav-toggle span {
  display: block;
  width: 100%;
  height: 2px;
  background: var(--color-text-main);
  transition: transform var(--transition-fast), opacity var(--transition-fast);
}

.nav-toggle[aria-expanded='true'] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.nav-toggle[aria-expanded='true'] span:nth-child(2) {
  opacity: 0;
}

.nav-toggle[aria-expanded='true'] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* Mobile full-screen nav overlay */
.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: var(--z-mobile-nav);
  background: var(--color-bg-base);
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Top-aligned (not centered) + scrollable: with 8 nav links + the language
     switcher + the CTA button, the full stack is taller than many real phone
     viewports (measured ~654px content in a 667px-tall viewport already
     leaves no margin) — centering it made the first item ("Home") render
     above the visible top edge with no way to scroll up to it. Starting
     below the header and allowing overflow-y scroll keeps every item
     reachable regardless of device height. */
  justify-content: flex-start;
  overflow-y: auto;
  gap: var(--space-lg);
  padding: calc(var(--header-height) + var(--space-lg)) var(--container-pad) var(--space-xl);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-12px);
  transition: opacity var(--transition-base), transform var(--transition-base), visibility var(--transition-base);
}

.mobile-nav.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.mobile-nav__list {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  font-family: var(--font-heading);
  font-size: 1.6rem;
  text-align: center;
}

.mobile-nav__lang {
  display: flex;
  gap: var(--space-sm);
  flex-wrap: wrap;
  justify-content: center;
  font-size: 0.9rem;
  font-weight: 700;
}

.mobile-nav__lang a[aria-current='true'] {
  color: var(--color-accent-gold);
}

body.nav-open {
  overflow: hidden;
}

/* ---------------------------------------------------------------------- */
/* WhatsApp floating button                                               */
/* ---------------------------------------------------------------------- */
/* Desktop-only: on mobile the sticky CTA bar already has its own WhatsApp
   button (green, see .btn-whatsapp), so this floating bubble stays hidden
   below the same 900px breakpoint the bar disappears at above — otherwise
   both were visible at once, an obvious duplicate. */
.whatsapp-float {
  display: none;
  position: fixed;
  right: var(--space-md);
  bottom: calc(var(--mobile-cta-height) + var(--space-md));
  z-index: var(--z-whatsapp);
  width: var(--whatsapp-size);
  height: var(--whatsapp-size);
  border-radius: 50%;
  background: #25D366;
  color: #0b0b0b;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  transition: transform var(--transition-fast);
}

.whatsapp-float:hover {
  transform: scale(1.06);
}

.whatsapp-float svg {
  width: 28px;
  height: 28px;
}

/* ---------------------------------------------------------------------- */
/* Mobile sticky CTA bar                                                  */
/* ---------------------------------------------------------------------- */
.mobile-cta-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-mobile-cta);
  height: var(--mobile-cta-height);
  display: flex;
  gap: var(--space-2xs);
  padding: var(--space-2xs) var(--space-sm);
  background: rgba(24, 24, 24, 0.96);
  border-top: 1px solid var(--color-border);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: transform var(--transition-base);
}

/* Uses its own state class (not the shared .is-hidden utility, which is
   display:none !important and would skip the slide-down transition) */
.mobile-cta-bar.is-tucked {
  transform: translateY(100%);
}

.mobile-cta-bar__btn {
  flex: 1;
  padding-block: 0.7rem;
  font-size: 0.85rem;
}

/* ---------------------------------------------------------------------- */
/* Cookie consent banner                                                  */
/* ---------------------------------------------------------------------- */
/* Sits at the TOP (not bottom) on purpose — the bottom of the viewport is
   already busy on mobile with the WhatsApp float + sticky CTA bar. */
.cookie-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--z-cookie-banner);
  background: rgba(16, 16, 16, 0.98);
  border-bottom: 1px solid var(--color-border);
  transform: translateY(-100%);
  transition: transform var(--transition-base);
}

.cookie-banner.is-visible {
  transform: translateY(0);
}

.cookie-banner__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  padding-block: var(--space-sm);
  text-align: center;
}

.cookie-banner__inner p {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  flex: 1;
  min-width: 220px;
}

.cookie-banner__inner a {
  color: var(--color-accent-gold);
  text-decoration: underline;
}

.cookie-banner__actions {
  display: flex;
  gap: var(--space-2xs);
  flex: none;
}

/* ---------------------------------------------------------------------- */
/* Footer                                                                 */
/* ---------------------------------------------------------------------- */
.site-footer {
  background: var(--color-bg-surface);
  border-top: 1px solid var(--color-border);
  padding-block: var(--space-xl) var(--space-lg);
  margin-bottom: var(--mobile-cta-height);
}

.site-footer__grid {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: 1fr;
}

.site-footer__brand {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.site-footer__tagline {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  max-width: 30ch;
}

/* NAP (Name/Address/Phone) block, added 2026-08-27 — the user wants this
   exact text (business name, address, phone) on every page, in every
   language, worded identically, for local-SEO/citation consistency.
   <address> is semantically correct for this but browsers italicize it
   by default, hence the reset. */
.site-footer__nap {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
  font-style: normal;
  font-size: var(--fs-small);
  color: var(--color-text-muted);
}

.site-footer__nap a {
  color: inherit;
}

.site-footer__nap a:hover {
  color: var(--color-accent-gold);
}

.site-footer__social-row {
  display: flex;
  gap: var(--space-2xs);
}

.site-footer__social {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--color-border);
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

.site-footer__social:hover {
  border-color: var(--color-accent-gold);
  color: var(--color-accent-gold);
}

.site-footer__social svg {
  width: 18px;
  height: 18px;
}

.site-footer__nav ul,
.site-footer__legal ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  font-size: var(--fs-small);
}

.site-footer__nav a:hover,
.site-footer__legal a:hover {
  color: var(--color-accent-gold);
}

.footer-link-btn {
  display: inline;
  padding: 0;
  cursor: pointer;
  text-align: left;
}

.footer-link-btn:hover {
  color: var(--color-accent-gold);
}

.site-footer__heading {
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  margin-bottom: var(--space-sm);
}

.site-footer__lang .lang-switcher__menu {
  position: static;
  opacity: 1;
  visibility: visible;
  transform: none;
  box-shadow: none;
  background: none;
  border: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.site-footer__lang .lang-switcher__menu a {
  padding: 0;
  font-size: var(--fs-small);
}

.site-footer__bottom {
  margin-top: var(--space-xl);
  padding-top: var(--space-md);
  border-top: 1px solid var(--color-border);
  font-size: var(--fs-small);
  color: var(--color-text-faint);
  text-align: center;
}

/* ==========================================================================
   Homepage sections
   ========================================================================== */

/* Hero */
.hero {
  position: relative;
  height: 100svh;
  min-height: 560px;
  overflow: hidden;
  display: flex;
  align-items: center;
}

.hero__slides {
  position: absolute;
  inset: 0;
}

.hero__slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  animation: heroSlideshow 18s infinite;
}

.hero__slide:nth-child(1) {
  animation-delay: 0s;
}

.hero__slide:nth-child(2) {
  animation-delay: 6s;
}

.hero__slide:nth-child(3) {
  animation: heroSlideshowGigantes 18s infinite;
  animation-delay: 12s;
  /* Los Gigantes slide: bias the Ken Burns zoom's anchor point toward the
     rocks (2026-08-23, nudged further the same day) so the slow zoom crops
     away sky from the top instead of expanding evenly — less empty sky
     above the rocks as it zooms in. Uses its own slightly deeper zoom
     (1.12 vs the other slides' 1.08) so there's enough crop room for the
     90/10 top/bottom split to read as a real shift, not just a redistribution
     of the same small budget. */
  transform-origin: 50% 90%;
  /* This slide's bright blue afternoon sky reads a bit low-contrast under
     the centered headline (2026-08-23, user feedback) — the shared
     .hero__overlay darkens all 3 slides equally, so this slide gets its own
     small extra darkening on top of that. */
  filter: brightness(0.88);
}

@keyframes heroSlideshow {
  0% { opacity: 0; transform: scale(1); }
  4% { opacity: 1; }
  30% { opacity: 1; transform: scale(1.08); }
  34% { opacity: 0; transform: scale(1.08); }
  100% { opacity: 0; }
}

@keyframes heroSlideshowGigantes {
  0% { opacity: 0; transform: scale(1); }
  4% { opacity: 1; }
  30% { opacity: 1; transform: scale(1.12); }
  34% { opacity: 0; transform: scale(1.12); }
  100% { opacity: 0; }
}

.hero__overlay {
  position: absolute;
  inset: 0;
  /* Widened/re-centered 2026-08-23 when the text block moved from bottom-
     anchored to vertically centered — the old gradient kept the top 40%
     nearly untouched and only got dark near the very bottom, which no
     longer covers where the text now sits. */
  background: linear-gradient(180deg, rgba(10, 10, 10, 0.32) 0%, rgba(10, 10, 10, 0.58) 38%, rgba(10, 10, 10, 0.62) 62%, rgba(10, 10, 10, 0.85) 100%);
}

.hero__content {
  position: relative;
  z-index: 1;
  max-width: 780px;
}

.hero__eyebrow {
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-gold-soft);
  margin-bottom: var(--space-sm);
}

.hero__headline {
  /* Smaller than the shared --fs-h1 (2026-08-23): the headline is now 3 short
     lines instead of 2, and the longest line across all 4 languages
     ("Experiencia cinematográfica") needs to stay on one line — verified by
     measuring each language's natural text width against the 740px hero
     content box at several viewport widths. */
  font-size: clamp(1.6rem, 3.6vw + 0.75rem, 3.4rem);
  margin-bottom: var(--space-sm);
}

.hero__headline strong {
  font-weight: 700;
}

.hero__subheadline {
  font-size: var(--fs-lead);
  color: var(--color-text-muted);
  margin-bottom: var(--space-lg);
  max-width: 52ch;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

/* Services */
.services__grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: 1fr;
}

.service-card {
  display: block;
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: 16px;
  overflow: hidden;
  transition: border-color var(--transition-fast), transform var(--transition-fast);
}

.service-card:hover {
  border-color: var(--color-accent-gold);
  transform: translateY(-2px);
}

.service-card__media img {
  aspect-ratio: 4 / 3;
  object-fit: cover;
  width: 100%;
}

.service-card__body {
  padding: var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.service-card__body p {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  margin-bottom: var(--space-2xs);
}

/* Portfolio preview */
.portfolio-preview__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-2xs);
}

/* Each tile links to the full portfolio (added 2026-08-27, matches the
   "Explore My Work" preview's purpose) — anchors are inline by default,
   block here so each tile fills its grid cell exactly like the bare <img>
   it replaced. */
.portfolio-preview__grid > a {
  display: block;
}

.portfolio-preview__grid img {
  /* Landscape-leaning "6x7" grid crop — most session photos are horizontal;
     this box only shapes the small preview tile, never the real photo (see
     portfolio.html's own grid + lightbox, which shows the true composition
     uncropped via object-fit: contain). */
  aspect-ratio: 7 / 6;
  object-fit: cover;
  border-radius: 8px;
}

/* 2026-08-24: this tile's box is narrower than the (1920x1280) source, so
   cover crops the sides. The man's shoulder/arm reaches the source photo's
   own right edge, so the crop needs to favor the right side to keep both his
   and the woman's shoulder in frame (round 1 went the wrong way — 35% shifted
   the window LEFT, cutting further into his shoulder; 95% shifts it right,
   keeping his shoulder intact with a small margin to spare). */
.portfolio-preview__grid a:nth-child(2) img {
  object-position: 70% center;
}

/* This tile's box is wider than the (1280x1920 portrait) source, so cover
   crops top/bottom — shifted up to show more sky, less sand (round 1 at 25%
   went too far and cut it right at her shadow's tip; 38% still shows more
   sky than the default center crop, but keeps her shadow plus a little sand
   beneath it in frame).
   2026-08-24: also nudged a little right (near, just left of, the right
   third-line) — but at this box/image ratio, cover already matches the box
   width exactly (no horizontal crop room to redistribute via object-position
   alone, unlike the vertical axis). A small extra zoom creates that room;
   since a plain transform on a bare <img> would paint outside its grid cell
   with nothing to clip it, this one image is wrapped in
   .portfolio-preview__item so the wrapper's overflow:hidden can clip it —
   the other 5 tiles stay bare <img>, matched by the rule above. */
.portfolio-preview__item {
  aspect-ratio: 7 / 6;
  overflow: hidden;
  border-radius: 8px;
}

.portfolio-preview__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Image 3 (2026-08-24, walked back): the horizontal nudge toward the right
   third-line needed a zoom (same zero-crop-room issue as image 2's sides),
   but the user asked to undo that and go back to the original, unzoomed
   size — just the vertical sky/sand bias that was already approved,
   letting cover crop the sides however it naturally does. Back to a bare
   <img>, no wrapper needed since there's no transform overflow to clip. */
.portfolio-preview__grid a:nth-child(3) img {
  object-position: center 38%;
}

/* Image 4 (2026-08-24, walked back): tried zooming this one too (like image
   5), but the user asked to undo it — keep it at its original, unzoomed
   size and just make sure the bottom of the photo is fully included rather
   than the top. At this box/image ratio cover already matches the box
   height exactly (zero vertical crop room to begin with — same reason
   object-position alone did nothing for image 2's sides), so bottom is
   already fully shown regardless of this value; set explicitly anyway to
   match what was asked, and in case that ever changes. */
.portfolio-preview__grid a:nth-child(4) img {
  object-position: center bottom;
}

/* Image 5: same box-crops-sides situation as image 2 — cover already
   matches the box height exactly, zero vertical crop room by default, so
   object-position alone can't reduce the gap above his head. Zoom +
   transform-origin anchored near where he already sits, so scaling pushes
   the empty sky above him out of frame without cropping into the family
   from below. */
.portfolio-preview__item--family-beach img {
  /* Smaller zoom than the other two — this photo's original bottom edge
     already sits fairly close to the kids' legs, so a bigger zoom risked
     cropping into them. 1.08 keeps that margin safe while still roughly
     halving the gap above the dad's head. */
  transform: scale(1.08);
  transform-origin: 50% 57%;
}

/* About preview */
.about-preview__grid {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: 1fr;
  align-items: center;
}

.about-preview__media img {
  border-radius: 16px;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

.about-preview__content p {
  color: var(--color-text-muted);
  margin-bottom: var(--space-md);
}

.about-preview__stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
}

.about-preview__stats li {
  font-size: var(--fs-small);
  color: var(--color-text-muted);
}

.about-preview__stats strong {
  display: block;
  font-family: var(--font-heading);
  font-size: 1.4rem;
  color: var(--color-accent-gold);
}

/* Testimonials
   2026-08-23: switched from a native overflow-x/scroll-snap track to a
   transform-based slider (JS drives .testimonials__track's translateX).
   Native smooth-scroll's duration scales with distance, and interacts
   unpredictably with scroll-snap on programmatic jumps — that's what made
   the autoplay's wrap-around (last card → first) visibly crawl/stick no
   matter how the scroll call was tuned. A CSS transition on transform has a
   fixed duration regardless of distance, so every step — including the
   wrap — now takes the same ~0.5s, no special-casing needed. */
.testimonials__viewport {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.testimonials__clip {
  overflow: hidden;
  flex: 1 1 auto;
  min-width: 0;
}

.testimonials__track {
  position: relative;
  display: flex;
  gap: var(--space-md);
  padding-block: var(--space-2xs);
  transition: transform 0.5s ease;
  touch-action: pan-y;
  cursor: grab;
  user-select: none;
}

.testimonials__track:active {
  cursor: grabbing;
}

.testimonials__track img {
  -webkit-user-drag: none;
  user-drag: none;
}

.testimonial-card {
  flex: 0 0 85%;
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: 16px;
  padding: var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.testimonial-card__media {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: 10px;
  margin-bottom: var(--space-2xs);
}

.testimonial-card__stars {
  color: var(--color-accent-gold);
  letter-spacing: 0.1em;
}

.testimonial-card__quote {
  color: var(--color-text-main);
  font-size: 0.95rem;
}

.testimonial-card__author {
  color: var(--color-text-faint);
  font-size: var(--fs-small);
}

.testimonials__arrow {
  flex: none;
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--color-border);
  font-size: 1.4rem;
  transition: border-color var(--transition-fast);
}

.testimonials__arrow:hover {
  border-color: var(--color-accent-gold);
  color: var(--color-accent-gold);
}

.testimonials__dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--space-2xs);
  margin-top: var(--space-md);
}

.testimonials__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(240, 235, 227, 0.25);
  transition: background-color var(--transition-fast), transform var(--transition-fast);
}

.testimonials__dot:hover {
  background: rgba(240, 235, 227, 0.5);
}

.testimonials__dot.is-active {
  background: var(--color-accent-gold);
  transform: scale(1.35);
}

/* Featured testimonial — a single standout quote, deliberately NOT part of
   the rotating carousel above. Full-bleed hero-banner treatment (background
   photo + overlay, like .final-cta) sets it apart visually: bigger type, no
   stars, no card chrome — this should read as one memorable highlight, not
   "one more review in the pile". */
.featured-testimonial {
  position: relative;
  overflow: hidden;
  min-height: 680px;
  display: flex;
  align-items: center;
  padding-block: var(--space-xl);
}

.featured-testimonial__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* This banner is wide/short relative to the source photo, so which axis
     gets cropped flips with viewport width: narrow screens crop
     horizontally (X matters — couple sits right-of-center), wide screens
     crop vertically (Y matters — his head sits near the very top of the
     original frame, so 0% pins it in view instead of centering into it). */
  object-position: 10% 0%;
}

/* Directional scrim, mirrored to match: right side (the couple) stays close
   to true brightness, left side (behind the text) darkens for legibility. */
.featured-testimonial__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(270deg,
    rgba(8, 8, 8, 0.05) 0%,
    rgba(8, 8, 8, 0.15) 30%,
    rgba(8, 8, 8, 0.5) 55%,
    rgba(8, 8, 8, 0.68) 100%);
}

.featured-testimonial__container {
  position: relative;
  width: 100%;
  display: flex;
  justify-content: flex-start;
}

.featured-testimonial__content {
  max-width: 400px;
  text-align: left;
}

.featured-testimonial__mark {
  display: block;
  font-family: var(--font-heading);
  font-size: 2.5rem;
  line-height: 1;
  color: var(--color-accent-gold);
  margin-bottom: var(--space-3xs);
}

.featured-testimonial__quote {
  font-family: var(--font-heading);
  font-style: italic;
  font-size: clamp(1rem, 0.5vw + 0.9rem, 1.2rem);
  line-height: 1.5;
  color: var(--color-text-main);
  margin-bottom: var(--space-md);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.5);
}

.featured-testimonial__author-row {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-3xs);
}

.featured-testimonial__author {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--color-text-main);
}

.featured-testimonial__ig-icon {
  width: 18px;
  height: 18px;
  flex: none;
  color: var(--color-accent-gold);
}

.featured-testimonial__source {
  margin-top: var(--space-3xs);
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

/* Mobile recomposition (2026-08-27): the desktop layout (couple kept
   visible via a narrow left-right scrim, text pinned left in the wide
   remaining space) breaks down once the box gets this narrow — cover
   crops so much off the sides at the full 680px height that the couple
   themselves fell out of frame entirely, leaving just harbor background.
   Below 768px this switches to a shorter banner (less height = less
   forced crop, so more of the original width survives) with the couple
   re-centered in what's now visible, and the text moves off the photo
   entirely — a bottom-anchored, centered band on its own dark gradient —
   so the two stop competing for the same narrow strip. */
@media (max-width: 767px) {
  .featured-testimonial {
    min-height: 560px;
    align-items: flex-end;
  }

  .featured-testimonial__bg {
    /* Re-centered on the couple for this box's own crop window (measured
       against the source photo — see BUILD_SPEC.md for the math). */
    object-position: 68% 0%;
  }

  .featured-testimonial__overlay {
    background: linear-gradient(0deg,
      rgba(8, 8, 8, 0.85) 0%,
      rgba(8, 8, 8, 0.65) 38%,
      rgba(8, 8, 8, 0.2) 68%,
      rgba(8, 8, 8, 0) 88%);
  }

  .featured-testimonial__container {
    justify-content: center;
  }

  .featured-testimonial__content {
    max-width: 100%;
    text-align: center;
  }

  .featured-testimonial__author-row {
    justify-content: center;
  }
}

/* Locations preview */
.locations-preview__grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: 1fr;
}

.location-card {
  position: relative;
  border-radius: 16px;
  overflow: hidden;
  /* Landscape-leaning "6x7", matching the Portfolio grid — this is just a
     teaser tile linking through to locations.html, not the real crop. */
  aspect-ratio: 7 / 6;
}

.location-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Los Gigantes teaser tile (2026-08-23): at this card's ~7:6 box, cover
   crops the sides only (box is narrower than the 16:9-ish source, so height
   matches exactly and object-position alone has no vertical room to work
   with) — same underlying issue as the hero slide. A small static zoom
   creates that room, biased toward the rocks so more sky crops away. */
.locations-preview__grid .location-card:nth-child(1) img {
  transform: scale(1.25);
  transform-origin: 50% 85%;
}

.location-card__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 40%, rgba(8, 8, 8, 0.85) 100%);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: var(--space-md);
}

/* Playa del Duque teaser tile (2026-08-23): bright sandy-beach photo reads
   low-contrast under the caption text with the shared overlay gradient
   above — darkened further just for this card. */
.locations-preview__grid .location-card:nth-child(4) .location-card__overlay {
  background: linear-gradient(180deg, transparent 25%, rgba(8, 8, 8, 0.92) 100%);
}

.location-card__overlay p {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  margin-top: var(--space-3xs);
}

/* Pricing preview */
.pricing-preview__grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: 1fr;
}

.pricing-card {
  position: relative;
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: 16px;
  padding: var(--space-lg) var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.pricing-card--featured {
  border-color: var(--color-accent-gold);
}

.pricing-card .badge {
  position: absolute;
  top: -14px;
  left: var(--space-md);
}

.pricing-card__price {
  font-family: var(--font-heading);
  font-size: 2.25rem;
  color: var(--color-accent-gold);
}

.pricing-card__features li {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  padding-block: var(--space-3xs);
  border-top: 1px solid var(--color-border);
}

.pricing-card__features li:first-child {
  border-top: none;
}

/* Instagram banner — deliberately smaller/lower-weight than Testimonials or
   Locations (static, manually updated, no official embed — see BUILD_SPEC.md
   section 11). Redesigned 2026-08-22: was a static 3x3 grid that read as a
   second portfolio; now a continuous auto-scrolling ticker of small thumbnails
   inside its own branded banner, framed by an Instagram badge + caption. */
.instagram-banner {
  --ig-item-size: 120px;
  position: relative;
  padding-block: var(--space-xl);
  background: linear-gradient(120deg, var(--color-bg-surface) 0%, #33241a 50%, var(--color-bg-surface) 100%);
  overflow: hidden;
}

.instagram-banner__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
}

.instagram-banner__badge {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--color-accent-gold-soft), var(--color-accent-gold), var(--color-sand-brown));
}

.instagram-banner__badge svg {
  width: 24px;
  height: 24px;
  color: var(--color-bg-base);
}

.instagram-banner__viewport {
  /* Capped so ~3 thumbnails show fully, with a 4th sliced by the mask fade —
     scales together with --ig-item-size per breakpoint below. */
  width: 100%;
  max-width: calc(var(--ig-item-size) * 3.5 + var(--space-3xs) * 3);
  margin-inline: auto;
  overflow: hidden;
  mask-image: linear-gradient(to right, transparent 0%, black 10%, black 90%, transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0%, black 10%, black 90%, transparent 100%);
}

.instagram-banner__track {
  display: flex;
  width: max-content;
  gap: var(--space-3xs);
  animation: instagram-scroll 38s linear infinite;
}

.instagram-banner__track:hover,
.instagram-banner__track:focus-within {
  animation-play-state: paused;
}

@keyframes instagram-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

.instagram-banner__item {
  display: block;
  flex: none;
  width: var(--ig-item-size);
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border-radius: 8px;
}

.instagram-banner__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.instagram-banner__caption {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .instagram-banner__track {
    animation: none;
  }

  .instagram-banner__viewport {
    overflow-x: auto;
  }
}

@media (min-width: 640px) {
  .instagram-banner {
    --ig-item-size: 160px;
  }
}

@media (min-width: 1024px) {
  .instagram-banner {
    --ig-item-size: 185px;
  }
}

/* Final CTA */
.final-cta {
  position: relative;
  padding-block: var(--space-2xl);
  text-align: center;
  overflow: hidden;
}

.final-cta__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.final-cta__overlay {
  position: absolute;
  inset: 0;
  background: var(--color-overlay-strong);
}

.final-cta__content {
  position: relative;
  z-index: 1;
  max-width: 640px;
}

.final-cta__content h2 {
  font-size: var(--fs-h2);
  margin-bottom: var(--space-lg);
}

.final-cta__content .hero__actions {
  justify-content: center;
}

/* ==========================================================================
   Inner pages (Services, Portfolio, Locations, ...)
   ========================================================================== */

/* Page hero banner — shared across inner pages */
.page-hero {
  position: relative;
  padding-block: calc(var(--header-height) + var(--space-2xl)) var(--space-2xl);
  overflow: hidden;
  text-align: center;
}

.page-hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.page-hero__overlay {
  position: absolute;
  inset: 0;
  background: var(--color-overlay-strong);
}

.page-hero__content {
  position: relative;
  z-index: 1;
  max-width: 720px;
  margin-inline: auto;
}

.page-hero__content h1 {
  font-size: var(--fs-h1);
  margin-bottom: var(--space-sm);
}

.page-hero__content p {
  color: var(--color-text-muted);
  font-size: var(--fs-lead);
}

/* Packages (Services page) */
.packages__intro {
  text-align: center;
  max-width: 56ch;
  margin: calc(-1 * var(--space-md)) auto var(--space-lg);
  color: var(--color-text-muted);
}

.packages__grid {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: 1fr;
}

/* Package story — the rich, narrative intro for each category's flagship
   package (e.g. "Love under the Sun"). Sits below the pricing grid (not
   inside any one pricing card — keeps all 3 tier cards uniformly compact),
   2026-08-27: reordered per the user's request so the 3 package cards lead
   and the fuller narrative follows. margin-top added (matching the
   pre-existing margin-bottom) since this block's own margin used to be the
   only thing spacing it from whatever came next — now that something
   (packages__grid) comes before it instead, it needs a top margin too, or
   that gap collapses to 0 (packages__grid has no margin-bottom of its own).
   See BUILD_SPEC.md section 4 / 4.1. */
.package-story {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: 1fr;
  align-items: center;
  margin-top: var(--space-xl);
  margin-bottom: var(--space-xl);
}

.package-story__media img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: 16px;
}

/* Couples story image (Los Gigantes) — default center crop cut into the
   man's shirt on the left edge; shift the crop window left (source-side)
   so a small gap remains between the frame and his shoulder. */
.packages__panel[data-category-panel="couples"] .package-story__media img {
  object-position: 44% center;
}

.package-story__eyebrow {
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-accent-gold-soft);
  margin-bottom: var(--space-2xs);
}

.package-story__content h3 {
  font-size: var(--fs-h2);
  margin-bottom: var(--space-sm);
}

.package-story__content p {
  color: var(--color-text-muted);
  margin-top: var(--space-sm);
}

.package-story__content p:first-of-type {
  margin-top: 0;
}

@media (min-width: 768px) {
  .package-story {
    grid-template-columns: 1fr 1.3fr;
  }
}

.package-card {
  position: relative;
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: 16px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.package-card .badge {
  position: absolute;
  top: var(--space-sm);
  left: var(--space-sm);
  z-index: 1;
}

.package-card__media {
  overflow: hidden;
}

.package-card__media img {
  aspect-ratio: 4 / 3;
  object-fit: cover;
  width: 100%;
}

/* "Love under the Sun: Experience" card ("Most Popular" badge, top-left):
   several rounds of transform:scale()+object-position tricks here proved
   unreliable across browsers (broke the card's box height, then left a
   visible gap) — abandoned that approach entirely. Image
   103-los-gigantes-maternity-couple-experience-card-crop.jpg is a
   pre-cropped 4:3 export of the same photo (see BUILD_SPEC.md) with the
   composition already baked in, so plain object-fit:cover needs no help. */

.package-card__body {
  padding: var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  flex: 1;
}

.package-card__audience {
  font-size: var(--fs-small);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-accent-gold-soft);
}

.package-card__price {
  font-family: var(--font-heading);
  font-size: 2rem;
  color: var(--color-accent-gold);
}

.package-card__features li {
  font-size: var(--fs-small);
  color: var(--color-text-muted);
  padding-block: 0.4rem;
  border-top: 1px solid var(--color-border);
}

.package-card__features li:first-child {
  border-top: none;
}

.packages__rush-note {
  text-align: center;
  margin-top: var(--space-lg);
  color: var(--color-text-muted);
  font-size: var(--fs-small);
}

/* Process video placeholder (shared: Services "how a session works" video,
   About page intro video — same visual pattern, different content) */
.process-video__placeholder {
  position: relative;
  max-width: 820px;
  margin-inline: auto;
  border-radius: 16px;
  overflow: hidden;
  aspect-ratio: 16 / 9;
}

.process-video__placeholder img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.process-video__play {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  background: rgba(10, 10, 10, 0.4);
}

.process-video__play-icon {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: rgba(240, 235, 227, 0.15);
  border: 1px solid rgba(240, 235, 227, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.process-video__play-icon svg {
  width: 26px;
  height: 26px;
  margin-left: 4px;
}

.process-video__meta {
  text-align: center;
  margin-top: var(--space-sm);
  color: var(--color-text-faint);
  font-size: var(--fs-small);
}

/* Accordion (details/summary) — Services FAQ + FAQ page */
.accordion {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  max-width: 780px;
  margin-inline: auto;
}

.accordion-item {
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  overflow: hidden;
}

.accordion-item summary {
  cursor: pointer;
  list-style: none;
  padding: var(--space-sm) var(--space-md);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-sm);
  font-weight: 700;
}

.accordion-item summary::-webkit-details-marker {
  display: none;
}

.accordion-item summary::after {
  content: '+';
  font-size: 1.4rem;
  line-height: 1;
  color: var(--color-accent-gold);
  flex: none;
  transition: transform var(--transition-fast);
}

.accordion-item[open] summary::after {
  transform: rotate(45deg);
}

.accordion-item__body {
  padding: 0 var(--space-md) var(--space-md);
  color: var(--color-text-muted);
  font-size: 0.95rem;
}

/* About page: narrow centered prose sections (My Approach, Before the
   Camera Comes Out, An Adventure Not a Photo Shoot, Languages) */
.about-block {
  max-width: 720px;
  margin-inline: auto;
  text-align: center;
}

.about-block + .about-block {
  margin-top: var(--space-2xl);
}

.about-block h2 {
  font-size: var(--fs-h3);
  margin-bottom: var(--space-sm);
}

.about-block p {
  color: var(--color-text-muted);
}

/* Legal pages (Privacy Policy, Aviso Legal, Cookie Policy) — left-aligned,
   unlike the centered marketing prose blocks elsewhere; long legal text
   reads poorly centered. */
.legal-content {
  max-width: 760px;
  margin-inline: auto;
}

.legal-content h2 {
  font-size: var(--fs-h3);
  margin-top: var(--space-xl);
  margin-bottom: var(--space-sm);
}

.legal-content h2:first-child {
  margin-top: 0;
}

.legal-content p,
.legal-content li {
  color: var(--color-text-muted);
  margin-top: var(--space-sm);
}

.legal-content ul {
  padding-left: 1.25rem;
  list-style: disc;
}

.legal-content__table-wrap {
  overflow-x: auto;
  margin-top: var(--space-sm);
}

.legal-content table {
  width: 100%;
  min-width: 480px;
  border-collapse: collapse;
  font-size: 0.9rem;
}

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

.legal-content th {
  color: var(--color-text-main);
  font-family: var(--font-body);
  font-weight: 700;
}

.legal-content td {
  color: var(--color-text-muted);
}

.legal-content__updated {
  color: var(--color-text-faint);
  font-size: var(--fs-small);
  margin-bottom: var(--space-lg);
}

.legal-content__notice {
  border-left: 3px solid var(--color-accent-gold);
  padding: var(--space-sm) var(--space-md);
  background: rgba(200, 144, 58, 0.08);
  border-radius: 0 8px 8px 0;
  margin-bottom: var(--space-lg);
}

.legal-content__notice p {
  margin-top: 0;
  color: var(--color-text-main);
  font-size: 0.95rem;
}

/* 404 page */
.error-page {
  text-align: center;
  padding-block: var(--space-2xl);
  min-height: 60vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.error-page__code {
  font-family: var(--font-heading);
  font-size: clamp(4rem, 12vw, 8rem);
  color: var(--color-accent-gold);
  line-height: 1;
}

.error-page__content p {
  color: var(--color-text-muted);
  max-width: 46ch;
  margin: var(--space-sm) auto var(--space-lg);
}

.error-page__actions {
  justify-content: center;
}

/* Contact page */
.contact-intro {
  max-width: 620px;
  margin: 0 auto var(--space-2xl);
  text-align: center;
}

.contact-intro p {
  color: var(--color-text-muted);
  font-size: var(--fs-lead);
}

.contact-intro p + p {
  margin-top: var(--space-md);
}

.contact-intro a {
  color: var(--color-accent-gold);
  border-bottom: 1px solid rgba(200, 144, 58, 0.4);
  transition: border-color var(--transition-fast);
}

.contact-intro a:hover {
  border-color: var(--color-accent-gold);
}

.contact-methods {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: 1fr;
  max-width: 900px;
  margin-inline: auto;
}

.contact-methods__consent {
  margin-top: var(--space-md);
  max-width: 900px;
  margin-inline: auto;
  text-align: center;
  font-size: var(--fs-small);
  color: var(--color-text-muted);
}

.contact-methods__consent a {
  color: inherit;
  text-decoration: underline;
}

.contact-methods__consent a:hover {
  color: var(--color-accent-gold);
}

.contact-method {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-2xs);
  padding: var(--space-lg) var(--space-md);
  border-radius: 16px;
  border: 1px solid var(--color-border);
  background: var(--color-bg-surface);
  transition: border-color var(--transition-fast), transform var(--transition-fast);
}

.contact-method:hover {
  border-color: var(--color-accent-gold);
  transform: translateY(-2px);
}

.contact-method__icon {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(200, 144, 58, 0.12);
  color: var(--color-accent-gold);
  margin-bottom: var(--space-2xs);
}

.contact-method__icon svg {
  width: 22px;
  height: 22px;
}

.contact-method__label {
  font-family: var(--font-heading);
  font-size: 1.25rem;
  color: var(--color-text-main);
}

.contact-method__detail {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
}

.contact-method--primary {
  border-color: var(--color-accent-gold);
  background: rgba(200, 144, 58, 0.08);
}

.contact-method--primary .contact-method__icon {
  background: var(--color-accent-gold);
  color: #181818;
}

/* FAQ page: category quick-links + per-category sections */
.faq-quicklinks {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2xs);
  margin-bottom: var(--space-2xl);
}

.faq-quicklinks a {
  padding: 0.5rem 1.1rem;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  font-size: var(--fs-small);
  font-weight: 700;
  color: var(--color-text-muted);
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

.faq-quicklinks a:hover {
  border-color: var(--color-accent-gold);
  color: var(--color-text-main);
}

.faq-category {
  scroll-margin-top: calc(var(--header-height) + var(--space-sm));
  max-width: 780px;
  margin-inline: auto;
}

.faq-category + .faq-category {
  margin-top: var(--space-2xl);
}

.faq-category h2 {
  font-size: var(--fs-h3);
  margin-bottom: var(--space-md);
}

/* Portfolio filter + grid */
.portfolio-filter,
.packages__tabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2xs);
  margin-bottom: var(--space-lg);
}

.portfolio-filter__btn,
.packages__tab {
  padding: 0.55rem 1.25rem;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  font-size: var(--fs-small);
  font-weight: 700;
  color: var(--color-text-muted);
  transition: background-color var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
}

.portfolio-filter__btn:hover,
.packages__tab:hover {
  border-color: var(--color-accent-gold);
  color: var(--color-text-main);
}

.portfolio-filter__btn.is-active,
.packages__tab.is-active {
  background: var(--color-accent-gold);
  border-color: var(--color-accent-gold);
  color: #181818;
}

.packages__panel-quote {
  max-width: 640px;
  margin: var(--space-lg) auto 0;
  text-align: center;
  font-style: italic;
  font-size: 1.1rem;
  color: var(--color-text-main);
}

.packages__panel-quote cite {
  display: block;
  margin-top: var(--space-xs);
  font-style: normal;
  font-size: var(--fs-small);
  color: var(--color-text-faint);
}

.portfolio-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-2xs);
}

.portfolio-grid__item {
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  border-radius: 8px;
  overflow: hidden;
}

.portfolio-grid__item img {
  width: 100%;
  /* Landscape-leaning "6x7" grid crop — most session photos are horizontal,
     and this box only shapes the grid tile. Click-through shows the real,
     uncropped composition (.lightbox__figure img, object-fit: contain). */
  aspect-ratio: 7 / 6;
  object-fit: cover;
  transition: transform var(--transition-base);
}

.portfolio-grid__item:hover img {
  transform: scale(1.04);
}

/* Garachico couple (image 50) — default center crop kept too much empty
   street on the left; the man already sits at the true right edge of the
   source photo (nothing left to crop there), so push all the way right. */
.portfolio-grid__item img[src*="50-garachico"] {
  object-position: 100% center;
}

/* Callao Salvaje maternity portrait (image 71) — default center crop cut
   into the top of her head/face and left extra room below her hands. Push
   the window up-source-side to show her full face with a small margin
   above the hair, cropping just slightly into the lower hand at the
   bottom (per explicit request). */
.portfolio-grid__item img[src*="71-callao-salvaje"] {
  object-position: center 37%;
}

/* Alcalá flamenco dancer (image 72) — the sharp figure sits on the left of
   the frame, her long-exposure ghost trail fades out to the right. Push
   all the way left-source-side (crop the fading trail) so she's composed
   toward the left of the tile. */
.portfolio-grid__item img[src*="72-alcala-varadero"] {
  object-position: 0% center;
}

.portfolio-grid__item.is-filtered-out {
  display: none;
}

/* Blog list (blog.html) — content here is placeholder (BUILD_SPEC.md
   section 10: the real content bank/post calendar is separate future work).
   Nav stays hidden (.is-hidden on the Blog link) until 6 real posts exist. */
.blog-grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: 1fr;
}

.blog-card {
  display: block;
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: 16px;
  overflow: hidden;
  transition: border-color var(--transition-fast), transform var(--transition-fast);
}

.blog-card:hover {
  border-color: var(--color-accent-gold);
  transform: translateY(-2px);
}

.blog-card__media img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

.blog-card__body {
  padding: var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.blog-card__tag {
  font-size: var(--fs-small);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-accent-gold-soft);
}

.blog-card__title {
  font-size: 1.15rem;
}

.blog-card__excerpt {
  color: var(--color-text-muted);
  font-size: 0.95rem;
}

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

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

/* Blog post template (blog-post.html) */
.blog-post__meta {
  display: flex;
  justify-content: center;
  gap: var(--space-sm);
  color: var(--color-text-faint);
  font-size: var(--fs-small);
  margin-bottom: var(--space-sm);
}

.blog-post__body {
  max-width: 720px;
  margin-inline: auto;
}

.blog-post__body p {
  color: var(--color-text-muted);
  margin-top: var(--space-md);
}

.blog-post__body h2 {
  font-size: var(--fs-h3);
  margin-top: var(--space-xl);
  margin-bottom: var(--space-sm);
}

.blog-post__body a {
  color: var(--color-accent-gold);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.blog-post__body a:hover {
  color: var(--color-accent-gold-soft);
}

.blog-post__image {
  margin: var(--space-lg) 0;
}

.blog-post__image img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: 16px;
}

.blog-post__image figcaption {
  margin-top: var(--space-2xs);
  color: var(--color-text-faint);
  font-size: var(--fs-small);
  text-align: center;
}

/* Post-to-post pager (prev/next), sits under the post body — solid, low-key,
   no arrows-in-circles gimmick. Works with 1 or 2 links present (a post at
   either end of the list just omits the missing side; .post-nav__link--next
   gets margin-left:auto to stay right-aligned when it's the only link). */
.post-nav {
  display: flex;
  justify-content: space-between;
  gap: var(--space-md);
  max-width: 720px;
  margin: var(--space-xl) auto 0;
  padding-top: var(--space-lg);
  border-top: 1px solid var(--color-border);
}

.post-nav__link {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  max-width: 46%;
  min-width: 0;
  color: var(--color-text-muted);
  transition: color var(--transition-fast);
}

.post-nav__link:hover {
  color: var(--color-accent-gold);
}

.post-nav__link--next {
  margin-left: auto;
  flex-direction: row-reverse;
  text-align: right;
}

.post-nav__arrow {
  flex: none;
  font-size: 1.3rem;
  line-height: 1;
  color: var(--color-accent-gold);
}

.post-nav__text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.post-nav__label {
  font-size: var(--fs-small);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-faint);
}

.post-nav__title {
  font-weight: 700;
  color: inherit;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 640px) {
  .post-nav__title {
    white-space: normal;
  }
}

/* Lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-lightbox);
  background: rgba(8, 8, 8, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--transition-base), visibility var(--transition-base);
}

.lightbox.is-open {
  opacity: 1;
  visibility: visible;
}

.lightbox__figure {
  max-width: min(90vw, 1100px);
  max-height: 85vh;
  margin: 0;
}

.lightbox__figure img {
  max-width: 100%;
  max-height: 85vh;
  object-fit: contain;
  border-radius: 8px;
}

.lightbox__close,
.lightbox__nav {
  position: absolute;
  border-radius: 50%;
  border: 1px solid rgba(240, 235, 227, 0.3);
  color: var(--color-text-main);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

.lightbox__close:hover,
.lightbox__nav:hover {
  border-color: var(--color-accent-gold);
  color: var(--color-accent-gold);
}

.lightbox__close {
  top: var(--space-md);
  right: var(--space-md);
  width: 44px;
  height: 44px;
  font-size: 1.5rem;
}

.lightbox__nav {
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
  font-size: 1.8rem;
}

.lightbox__nav--prev {
  left: var(--space-md);
}

.lightbox__nav--next {
  right: var(--space-md);
}

/* Location cards (Locations page) — compact by default (image + name +
   short teaser), expand in place on click to reveal the full description.
   The open card spans the full grid width (grid-column: 1 / -1), which
   pushes every following card down to a new row automatically — no JS
   reflow logic needed, CSS Grid auto-placement handles it.
   Named .location-item (not .location-card) on purpose — .location-card is
   already used by the homepage Locations Preview overlay cards, and reusing
   that name here caused its aspect-ratio: 4/5 rule to force this card to
   ~1475px tall regardless of content once it spanned the full grid width. */
.locations-grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: 1fr;
}

.location-item {
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: 16px;
  overflow: hidden;
}

.location-item.is-open {
  grid-column: 1 / -1;
}

/* .location-item__row holds the photo and the text content as siblings, so
   the full description sits next to the image once open — not just the
   short teaser, with the long text dangling full-width underneath it. */
.location-item__row {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.location-item__photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  flex: none;
  display: block;
  cursor: pointer;
}

/* Vilaflor and Santa Cruz: two rounds of transform:scale() (even a subtle
   4%) visibly grew the compact card's box height in some browsers —
   aspect-ratio + transform is a known rough edge, not worth chasing
   further. Simple fix instead: a second, separately pre-cropped image file
   with the wanted composition already baked in, swapped in for the
   compact card view via plain CSS display — no transform, no positioning
   tricks. The original file stays for the expanded (.is-open) view, which
   always shows the real, untouched composition. */
.location-item__photo--full {
  display: none;
}

.location-item.is-open .location-item__photo--compact {
  display: none;
}

.location-item.is-open .location-item__photo--full {
  display: block;
}

/* Expanded card: drop the fixed crop and show the photo's real composition
   uncropped (horizontal, vertical, panoramic — whatever it actually is),
   per the photographer's explicit call that composition isn't standardized. */
.location-item.is-open .location-item__photo {
  aspect-ratio: auto;
  object-fit: contain;
  max-height: 60vh;
}

.location-item__content {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.location-item__toggle {
  display: flex;
  align-items: flex-start;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: var(--space-md);
  padding-right: calc(var(--space-md) + 1.5rem);
  color: inherit;
  cursor: pointer;
  position: relative;
}

.location-item__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.location-item__name {
  font-family: var(--font-heading);
  font-size: 1.25rem;
}

.location-item__teaser {
  color: var(--color-text-muted);
  font-size: 0.95rem;
}

.location-item__chevron {
  position: absolute;
  top: var(--space-md);
  right: var(--space-md);
  color: var(--color-accent-gold);
  transition: transform var(--transition-fast);
}

.location-item.is-open .location-item__chevron {
  transform: rotate(180deg);
}

.location-item__full {
  max-height: 0;
  overflow: hidden;
  transition: max-height var(--transition-base);
}

.location-item__full-inner {
  padding: 0 var(--space-md) var(--space-md);
}

.location-item__full-inner p {
  color: var(--color-text-muted);
  font-size: 0.95rem;
  line-height: 1.55;
  margin-top: var(--space-sm);
}

.location-item__full-inner p:first-child {
  margin-top: 0;
}

.location-item__tip {
  font-size: 0.9rem;
}

.location-item__tip strong {
  color: var(--color-text-main);
}

/* Vilaflor's Teide National Park permit disclaimer — kept visually distinct
   on purpose, see BUILD_SPEC.md section 6.1: this protects against a real
   legal/financial risk and must not get lost among the regular copy. */
.location-item__notice {
  border-left: 3px solid var(--color-accent-gold);
  padding-left: var(--space-sm);
  background: rgba(200, 144, 58, 0.08);
  border-radius: 0 8px 8px 0;
}

.location-item__notice strong {
  color: var(--color-accent-gold-soft);
}

@media (min-width: 640px) {
  /* Open card: photo and ALL the text (name, teaser, full description, tip)
     sit side by side as one balanced row — not just the photo next to the
     short teaser, with the long description dangling full-width beneath. */
  .location-item.is-open .location-item__row {
    flex-direction: row;
    align-items: stretch;
    gap: var(--space-lg);
  }

  .location-item.is-open .location-item__photo {
    width: 45%;
    flex: none;
    aspect-ratio: auto;
    height: auto;
    max-height: 480px;
    object-fit: contain;
  }

  .location-item.is-open .location-item__content {
    flex: 1;
    justify-content: center;
  }

  .location-item.is-open .location-item__toggle {
    padding-bottom: var(--space-sm);
  }
}

/* ==========================================================================
   Breakpoints
   ========================================================================== */
@media (min-width: 640px) {
  .services__grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .locations-preview__grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .pricing-preview__grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .testimonial-card {
    flex: 0 0 60%;
  }

  .portfolio-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .locations-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .contact-methods {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (min-width: 768px) {
  .site-footer__grid {
    grid-template-columns: 1.4fr 1fr 1fr 1fr;
  }

  .about-preview__grid {
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 900px) {
  .site-nav {
    display: block;
  }

  .site-header__cta {
    display: inline-flex;
  }

  .nav-toggle {
    display: none;
  }

  .mobile-cta-bar {
    display: none;
  }

  .whatsapp-float {
    display: flex;
    bottom: var(--space-md);
  }

  .site-footer {
    margin-bottom: 0;
  }

  .hero__actions .btn {
    padding-inline: 2.25rem;
  }

  .testimonials__arrow {
    display: flex;
  }

  .testimonial-card {
    flex: 0 0 calc(33.333% - var(--space-md) * 2 / 3);
  }
}

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

  .portfolio-preview__grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .locations-preview__grid {
    grid-template-columns: repeat(4, 1fr);
  }

  .pricing-preview__grid {
    grid-template-columns: repeat(3, 1fr);
  }

  /* Category filters keep a 3x3 grid at desktop for symmetry (9 items each);
     only the unfiltered "All" view (28 items) widens to 4 columns. */
  .portfolio-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .portfolio-grid.portfolio-grid--wide {
    grid-template-columns: repeat(4, 1fr);
  }

  /* 8 cards -> 2x4 at desktop for a symmetric grid */
  .locations-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

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

/* ==========================================================================
   Accessibility: reduced motion
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .hero__slide {
    animation: none;
    opacity: 0;
  }

  .hero__slide:first-child {
    opacity: 1;
  }
}
