/* ==========================================================================
   MERLIN MORENO — Fotografía Editorial
   ========================================================================== */

:root {
  --color-black: #0b0b0a;
  --color-ink: #171613;
  --color-white: #f7f4ee;
  --color-paper: #efeae1;
  --color-gray-300: #cfc9bc;
  --color-gray-500: #6f695c;   /* darkened from #948d7e — original failed WCAG AA (3:1) as text */
  --color-gray-700: #524c40;
  --color-accent: #a68a5c;
  --color-accent-text: #7c6744; /* accent, darkened for use as text on light backgrounds (AA 4.5:1+) */

  /* Fine hairline borders — a translucent tint of --color-ink rather than a
     flat gray, so the same token reads correctly over both paper and photo
     backgrounds without a separate dark-mode variant. */
  --color-border: rgba(23, 22, 19, 0.09);
  --color-border-strong: rgba(23, 22, 19, 0.16);

  --font-display: 'Fraunces', Georgia, serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-soft: cubic-bezier(0.22, 1, 0.36, 1);

  /* One motion language, three weights. Every transition/animation in the
     site picks one of these instead of an ad-hoc value, so hovers, toggles
     and reveals all feel like the same hand. */
  --dur-fast: 0.3s;   /* pure opacity/color state flips, no movement */
  --dur-base: 0.45s;  /* standard hover — small movement + color together */
  --dur-slow: 0.65s;  /* deliberate movement — lifts, panels, zooms */

  /* Multi-layer shadow scale — a tight contact shadow plus a soft ambient
     one at every step, instead of one flat blur. Reused by every card/
     button hover in the site so elevation always reads the same way. */
  --shadow-xs: 0 1px 2px rgba(11, 11, 10, 0.04), 0 1px 1px rgba(11, 11, 10, 0.03);
  --shadow-sm: 0 2px 6px -2px rgba(11, 11, 10, 0.08), 0 6px 16px -8px rgba(11, 11, 10, 0.10);
  --shadow-md: 0 8px 24px -10px rgba(11, 11, 10, 0.18), 0 24px 48px -24px rgba(11, 11, 10, 0.16);
  --shadow-lg: 0 16px 40px -16px rgba(11, 11, 10, 0.24), 0 45px 80px -50px rgba(11, 11, 10, 0.35);

  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 22px;

  --container: min(92vw, 1440px);
  --gutter: clamp(1.25rem, 3vw, 3rem);

  /* Tiered vertical rhythm — deliberately different per transition instead
     of one repeated section-pad. Mobile (the clamp minimum) is what matters
     most, since that's where excess space is felt hardest. Widened ~6-8%
     from the previous scale for a slightly more generous, premium breathing
     room without disturbing the relative rhythm between tiers. */
  --space-generous: clamp(4.75rem, 12.5vw, 9.75rem); /* hero exit, before contact */
  --space-standard: clamp(4rem, 10.5vw, 8rem);       /* most section transitions */
  --space-contained: clamp(3.5rem, 8.5vw, 6.5rem);   /* dense/casual sections */

  --header-h: 88px;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html { scroll-behavior: auto; }
img, picture, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; background: none; border: none; }
ul { list-style: none; }

html, body { height: 100%; }
body {
  background: var(--color-white);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-weight: 300;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

::selection { background: var(--color-black); color: var(--color-white); }

/* ---------- Utility / Skip link ---------- */
.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--color-black);
  color: var(--color-white);
  padding: 1rem 1.5rem;
  z-index: 999;
}
.skip-link:focus { left: 0; }

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

/* ---------- Film grain overlay ---------- */
.grain {
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- Preloader ---------- */
.preloader {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: var(--color-black);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Hard CSS-only fallback: if JS fails to hide this (blocked script,
     thrown error before hidePreloader runs), it would otherwise sit on
     top of the whole page and swallow every click forever. This timer
     runs independent of any JS timer/rAF, so the page always becomes
     clickable a few seconds in even in the worst case. */
  animation: preloader-unlock 0s 4s forwards;
}
@keyframes preloader-unlock {
  to { pointer-events: none; }
}
.preloader-word {
  font-family: var(--font-display);
  font-style: italic;
  color: var(--color-white);
  font-size: clamp(1.5rem, 4vw, 2.5rem);
  letter-spacing: 0.04em;
  opacity: 0;
}

/* ---------- Custom cursor ---------- */
.cursor { position: fixed; inset: 0; pointer-events: none; z-index: 9998; opacity: 0; transition: opacity var(--dur-fast) var(--ease-out); }
.cursor.is-active { opacity: 1; }
.cursor-dot, .cursor-ring {
  position: fixed;
  top: 0; left: 0;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  mix-blend-mode: difference;
}
.cursor-dot {
  width: 7px; height: 7px;
  background: var(--color-white);
  transition: opacity var(--dur-fast) var(--ease-out);
}
.cursor-ring {
  width: 44px; height: 44px;
  border: 1px solid var(--color-white);
  transition: width var(--dur-base) var(--ease-out), height var(--dur-base) var(--ease-out);
  display: flex; align-items: center; justify-content: center;
}
/* One hover state for every interactive/viewable target — a gallery item
   and a button read the same way, instead of two competing cursor sizes. */
.cursor.is-hover .cursor-ring { width: 68px; height: 68px; }

@media (hover: none), (pointer: coarse) {
  .cursor { display: none; }
}

/* Hide the native cursor once the custom one is confirmed active (fine pointer only) */
html.has-custom-cursor a,
html.has-custom-cursor button,
html.has-custom-cursor input,
html.has-custom-cursor textarea,
html.has-custom-cursor select {
  cursor: none;
}

/* ---------- Scroll progress ---------- */
.scroll-progress {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: var(--color-accent);
  transform: scaleX(0);
  transform-origin: left;
  z-index: 1200;
  pointer-events: none;
}

/* ---------- Floating WhatsApp CTA ---------- */
/* Hidden until the visitor scrolls past the hero (avoids duplicating the
   hero's own CTA), and hidden again while the cinema section is on screen
   so it never overlaps the sound-toggle button in the same corner. */
.whatsapp-float {
  position: fixed;
  right: clamp(1rem, 3vw, 1.5rem);
  bottom: clamp(1rem, 3vw, 1.5rem);
  z-index: 900;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-black);
  color: var(--color-white);
  box-shadow: 0 16px 32px -14px rgba(11, 11, 10, 0.45);
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out), background-color var(--dur-base) var(--ease-out);
}
.whatsapp-float.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
.whatsapp-float.is-suppressed { opacity: 0; transform: translateY(12px); pointer-events: none; }
.whatsapp-float:hover { background: var(--color-accent-text); }
.whatsapp-float svg { width: 24px; height: 24px; }

@media (max-width: 560px) {
  .whatsapp-float { width: 48px; height: 48px; }
  .whatsapp-float svg { width: 22px; height: 22px; }
}

/* ==========================================================================
   Header / Nav
   ========================================================================== */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 1000;
  height: var(--header-h);
  display: flex;
  align-items: center;
  mix-blend-mode: difference;
  transition: transform var(--dur-slow) var(--ease-out), mix-blend-mode var(--dur-fast) linear;
}
.site-header.is-hidden { transform: translateY(-100%); }
/* Past the hero, the invert-against-anything trick has done its job —
   switch to a real floating surface (see .nav-desktop/.menu-toggle below)
   instead of blending, so the backdrop-blur glass actually reads as glass. */
.site-header.is-scrolled { mix-blend-mode: normal; }

.header-inner {
  width: var(--container);
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  color: var(--color-white);
}


.nav-desktop {
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 2.5vw, 2.75rem);
  border-radius: 999px;
  border: 1px solid transparent;
  transition: background-color var(--dur-slow) var(--ease-out), border-color var(--dur-slow) var(--ease-out),
    box-shadow var(--dur-slow) var(--ease-out), padding var(--dur-slow) var(--ease-out), color var(--dur-slow) var(--ease-out);
}
/* Floating premium bar — appears once the page has scrolled past the hero.
   Backdrop-blur glass over a translucent paper tint, a hairline border and
   a soft ambient shadow; text switches to ink since the surface is light. */
.site-header.is-scrolled .nav-desktop {
  background: rgba(247, 244, 238, 0.78);
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  border-color: var(--color-border-strong);
  box-shadow: var(--shadow-md);
  padding: 0.55rem 0.6rem 0.55rem 1.75rem;
  color: var(--color-ink);
}
.nav-desktop a {
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  position: relative;
  padding-bottom: 4px;
}
/* Shared editorial underline — every plain-text link in the page (nav,
   footer, contact list, plans note) reveals the same way on hover so
   the interaction reads as one system, not several. */
.nav-desktop a::after,
.footer-top-link::after,
.footer-bottom nav a::after,
.contact-details a::after,
.plans-note a::after,
.portfolio-cta a::after,
.footer-cta a::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-base) var(--ease-out);
}
.nav-desktop a:hover::after,
.footer-top-link:hover::after,
.footer-bottom nav a:hover::after,
.contact-details a:hover::after,
.plans-note a:hover::after,
.portfolio-cta a:hover::after,
.footer-cta a:hover::after {
  transform: scaleX(1);
  transform-origin: left;
}
/* A quick press cue on every link in this shared system — mostly felt on
   touch, where :hover never fires but :active does for the brief moment
   of the tap. Opacity only (no movement) so it never fights the underline
   reveal running at the same time. */
.nav-desktop a,
.footer-top-link,
.footer-bottom nav a,
.contact-details a,
.plans-note a,
.portfolio-cta a,
.footer-cta a {
  transition: opacity var(--dur-fast) var(--ease-out);
}
.nav-desktop a:active,
.footer-top-link:active,
.footer-bottom nav a:active,
.contact-details a:active,
.plans-note a:active,
.portfolio-cta a:active,
.footer-cta a:active {
  opacity: 0.6;
}
.nav-cta {
  border: 1px solid currentColor;
  border-radius: 999px;
  padding: 0.6rem 1.2rem !important;
  letter-spacing: 0.08em;
}
.nav-cta::after { display: none; }

.menu-toggle {
  display: none;
  width: 46px; height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(247, 244, 238, 0.4);
  position: relative;
  z-index: 1100;
  color: var(--color-white);
  transition: border-color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out),
    background-color var(--dur-slow) var(--ease-out), backdrop-filter var(--dur-slow) var(--ease-out),
    box-shadow var(--dur-slow) var(--ease-out), color var(--dur-slow) var(--ease-out);
}
.menu-toggle:hover { border-color: rgba(247, 244, 238, 0.9); transform: scale(1.06); }
.menu-toggle:active { transform: scale(0.96); transition-duration: var(--dur-fast); }
/* Mirrors the desktop pill's glass treatment once scrolled (mobile only —
   nav-desktop is hidden below 1024px, this is the only header chrome
   visitors see there). */
.site-header.is-scrolled .menu-toggle {
  background: rgba(247, 244, 238, 0.78);
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  border-color: var(--color-border-strong);
  box-shadow: var(--shadow-sm);
  color: var(--color-ink);
}
.site-header.is-scrolled .menu-toggle:hover { border-color: var(--color-ink); }
.menu-toggle span {
  position: absolute;
  top: 50%;
  left: 14px; right: 14px;
  height: 1px;
  background: currentColor;
  transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}
.menu-toggle span:nth-child(1) { transform: translateY(-4.5px); }
.menu-toggle span:nth-child(2) { transform: translateY(4.5px); }
.menu-toggle[aria-expanded="true"],
.site-header.is-scrolled .menu-toggle[aria-expanded="true"] {
  mix-blend-mode: normal;
  color: var(--color-white);
  border-color: rgba(255, 255, 255, 0.9);
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}
.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(0) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { transform: translateY(0) rotate(-45deg); }

.mobile-menu {
  position: fixed;
  inset: 0;
  /* Same warm-glow-over-black recipe already used on .hero-overlay — two
     soft accent-toned radial glows from opposite corners, not a new
     treatment, just reused in this context. */
  background:
    radial-gradient(140% 90% at 85% 0%, rgba(166, 138, 92, 0.14) 0%, rgba(166, 138, 92, 0) 55%),
    radial-gradient(120% 70% at 15% 100%, rgba(166, 138, 92, 0.1) 0%, rgba(166, 138, 92, 0) 60%),
    var(--color-black);
  color: var(--color-white);
  z-index: 1050;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(1.5rem, 6vh, 3rem) var(--gutter);
  overflow-y: auto;
  transform: translateY(-100%);
  transition: transform var(--dur-slow) var(--ease-out);
}
.mobile-menu.is-open { transform: translateY(0); }
/* Dedicated in-panel close control — top-right, aligned with the panel's
   own top/right margins. Same circular icon-button treatment as
   .lightbox-close/.service-back-circle; same X built from two rotated
   lines as .lightbox-close-icon. */
.mobile-menu-close {
  position: absolute;
  top: clamp(1.25rem, 3vw, 2.25rem);
  right: var(--gutter);
  z-index: 1;
  width: 42px;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(247, 244, 238, 0.06);
  border: 1px solid rgba(247, 244, 238, 0.3);
  color: var(--color-white);
  transition: background-color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.mobile-menu-close:hover,
.mobile-menu-close:focus-visible {
  background: rgba(247, 244, 238, 0.14);
  border-color: rgba(247, 244, 238, 0.6);
  transform: scale(1.06);
}
.mobile-menu-close:active { transform: scale(0.94); transition-duration: var(--dur-fast); }
.mobile-menu-close-icon { position: relative; width: 14px; height: 14px; }
.mobile-menu-close-icon::before,
.mobile-menu-close-icon::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
}
.mobile-menu-close-icon::before { transform: rotate(45deg); }
.mobile-menu-close-icon::after { transform: rotate(-45deg); }
.mobile-menu nav { display: flex; flex-direction: column; gap: 1rem; counter-reset: menu-item; }
.mobile-menu nav a {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 1rem;
  font-family: var(--font-display);
  font-size: clamp(2rem, 9vw, 3rem);
  font-style: italic;
  opacity: 0;
  transition: transform var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
  counter-increment: menu-item;
}
.mobile-menu nav a::before {
  content: '0' counter(menu-item);
  font-family: var(--font-body);
  font-style: normal;
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  color: var(--color-accent);
}
.mobile-menu nav a:hover,
.mobile-menu nav a:focus-visible {
  color: var(--color-accent);
  transform: translateX(0.4em);
}
.mobile-menu nav a:active {
  color: var(--color-accent);
  transform: translateX(0.4em) scale(0.98);
  transition-duration: var(--dur-fast);
}
.mobile-menu.is-open nav a { animation: menuIn var(--dur-slow) var(--ease-out) forwards; }
.mobile-menu nav a:nth-child(1) { animation-delay: 0.05s; }
.mobile-menu nav a:nth-child(2) { animation-delay: 0.1s; }
.mobile-menu nav a:nth-child(3) { animation-delay: 0.15s; }
.mobile-menu nav a:nth-child(4) { animation-delay: 0.2s; }
.mobile-menu nav a:nth-child(5) { animation-delay: 0.25s; }
.mobile-menu nav a:nth-child(6) { animation-delay: 0.3s; }
.mobile-menu nav a:nth-child(7) { animation-delay: 0.35s; }
.mobile-menu nav a:nth-child(8) { animation-delay: 0.4s; }
@keyframes menuIn { to { opacity: 1; } }

.mobile-menu-footer {
  display: flex;
  justify-content: space-between;
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(255,255,255,0.2);
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  color: var(--color-gray-300);
}

/* ==========================================================================
   Hero
   ========================================================================== */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  background: var(--color-black);
}
.hero-media { position: absolute; inset: 0; }
/* Shared by the current photo and whatever media fills this slot later
   (a video would sit here with the exact same rules) — sizing/position
   logic lives once, independent of what the actual element turns out to
   be. Only the source ever needs to change. */
.hero-media img,
.hero-media video {
  width: 100%; height: 100%;
  object-fit: cover;
  /* Square source, face roughly centered with the eyes a little above
     the vertical midpoint — this keeps the face safely in frame on both
     tall (mobile) and short/wide (desktop) viewports while showing a bit
     more of the hair than a dead-center crop would. */
  object-position: center 35%;
  transform: scale(1.08);
}
.hero-overlay {
  position: absolute; inset: 0;
  /* Three layers doing three separate jobs: a warm glow behind the text
     block, a tighter dark "spotlight" concentrated right behind the type
     (the actual legibility guarantee — everything else stays honest to the
     photo instead of one flat dark band), and a soft vignette on the
     opposite corner for depth. All three read as "this photo just has
     nice light," never as a visible overlay. */
  background:
    radial-gradient(120% 70% at 15% 100%, rgba(166, 138, 92, 0.14) 0%, rgba(166, 138, 92, 0) 55%),
    radial-gradient(85% 60% at 20% 100%, rgba(11, 11, 10, 0.5) 0%, rgba(11, 11, 10, 0) 62%),
    radial-gradient(140% 90% at 85% 0%, rgba(11, 11, 10, 0.22) 0%, rgba(11, 11, 10, 0) 60%),
    linear-gradient(180deg, rgba(11,11,10,0.24) 0%, rgba(11,11,10,0.05) 35%, rgba(11,11,10,0.62) 100%);
}
.hero-brand {
  position: absolute;
  top: clamp(1.25rem, 3vw, 2.25rem);
  left: 0;
  right: 0;
  z-index: 2;
  width: var(--container);
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.hero-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid rgba(247, 244, 238, 0.4);
  /* The shell mark is a dark silhouette — without a light backing it
     disappears against the hero's own dark photo/video. */
  background: rgba(247, 244, 238, 0.92);
  font-family: var(--font-display);
  font-style: italic;
  font-size: 0.8rem;
  color: var(--color-ink);
  flex-shrink: 0;
  overflow: hidden;
}
.hero-logo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hero-brand-text {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  line-height: 1;
}
.hero-name {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(0.95rem, 1.6vw, 1.2rem);
  color: var(--color-white);
  opacity: 0.92;
}
/* Quiet, tracked-caps wordmark subtitle — deliberately plain sans (not the
   display serif) and low opacity so it reads as a discreet descriptor under
   the name, never competing with it. */
.hero-tagline {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: clamp(0.5rem, 0.75vw, 0.58rem);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-white);
  opacity: 0.62;
}
.hero-content {
  position: relative;
  z-index: 2;
  width: var(--container);
  margin: 0 auto;
  padding: 0 0 clamp(1.25rem, 3.5vw, 2rem);
  color: var(--color-white);
}
.hero-title {
  font-family: var(--font-display);
  font-weight: 400;
  /* ~10% smaller than before so it never crowds the name badge pinned
     at the top-left, even on shorter laptop viewports. */
  font-size: clamp(2.9rem, 9vw, 8.1rem);
  line-height: 0.98;
  letter-spacing: -0.01em;
  margin-bottom: 2.25rem;
}
.hero-title em { font-style: italic; font-weight: 300; }
.hero-title .line {
  display: flex;
  flex-wrap: wrap;
  overflow: visible;
}
.word-mask {
  display: inline-block;
  overflow: hidden;
  padding-bottom: 0.1em;
  margin-bottom: -0.1em;
  margin-right: 0.28em;
}
.word-mask .word {
  display: inline-block;
  will-change: transform;
}

/* Large desktop only — the 8.1rem ceiling above was tuned to never crowd
   the name badge on shorter *laptop* screens, a real constraint at
   ~1280-1440px. Past 1600px there's headroom the clamp() was leaving on
   the table: let the title actually dominate, with a touch more negative
   tracking (standard at larger display sizes) and a little more room to
   breathe before the viewport edge. */
@media (min-width: 1600px) {
  .hero-title {
    font-size: clamp(8.1rem, 8.5vw, 10.5rem);
    letter-spacing: -0.02em;
  }
  .hero-content { padding-bottom: clamp(2rem, 4vw, 3rem); }
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}
/* Deliberately compact on the phone width this was originally tuned for —
   two buttons need to sit in one row without crowding the trust line below.
   From tablet up there's no such constraint, and a 9px CTA next to a
   130px+ title reads as an afterthought, not a confident action — see
   MEJORAS CRÍTICAS. */
.hero-actions .btn {
  width: auto;
  padding: 0.5rem 0.85rem;
  font-size: 0.58rem;
  gap: 0.35rem;
  justify-content: center;
  white-space: nowrap;
}
@media (min-width: 640px) {
  .hero-actions .btn {
    padding: 0.9rem 1.85rem;
    font-size: 0.76rem;
    gap: 0.5rem;
  }
}

.hero-trust {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}
.hero-trust-avatars { display: flex; flex-shrink: 0; }
/* Real client-session photos, cropped into small circles — the flat-color
   background per child is kept as a fallback behind the <img> (shows
   through only if a photo fails to load), same palette as the rest of
   the site. */
.hero-trust-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid var(--color-ink);
  background: var(--color-gray-300);
  margin-left: -10px;
  overflow: hidden;
}
.hero-trust-avatar:first-child { margin-left: 0; }
.hero-trust-avatar:nth-child(2) { background: var(--color-accent); }
.hero-trust-avatar:nth-child(3) { background: var(--color-white); }
.hero-trust-avatar:nth-child(4) { background: rgba(166, 138, 92, 0.5); }
.hero-trust-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--dur-slow) var(--ease-out);
}
.hero-trust-avatar:hover img { transform: scale(1.15); }
.hero-trust-info { display: flex; flex-direction: column; gap: 0.15rem; }
.hero-trust-rating {
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
  font-family: var(--font-display);
  font-size: 0.68rem;
  color: var(--color-white);
}
.hero-trust-stars { color: var(--color-accent); font-size: 0.62rem; letter-spacing: 0.05em; }
.hero-trust-rating strong { font-weight: 500; }
.hero-trust-caption {
  font-size: 0.58rem;
  color: rgba(247, 244, 238, 0.72);
  line-height: 1.4;
}
@media (min-width: 640px) {
  .hero-trust-avatar { width: 34px; height: 34px; margin-left: -12px; }
  .hero-trust-rating { font-size: 0.8rem; }
  .hero-trust-stars { font-size: 0.72rem; }
  .hero-trust-caption { font-size: 0.68rem; }
}

.btn-accent {
  background: var(--color-accent);
  color: var(--color-black);
  border-color: var(--color-accent);
}
/* Solid fill on hover (not transparent) so this reads correctly regardless
   of what's behind it — used on both the dark hero photo and the light
   featured plan card. */
.btn-accent:hover { background: var(--color-accent-text); color: var(--color-white); border-color: var(--color-accent-text); }

/* ---------- Hero frame marks (viewfinder motif) ---------- */
.hero-frame span {
  position: absolute;
  width: 22px;
  height: 22px;
  border-color: rgba(247, 244, 238, 0.55);
  border-style: solid;
  border-width: 0;
  z-index: 2;
}
.hero-frame .corner-tl { top: clamp(1.25rem, 3vw, 2.25rem); left: var(--gutter); border-top-width: 1px; border-left-width: 1px; }
.hero-frame .corner-tr { top: clamp(1.25rem, 3vw, 2.25rem); right: var(--gutter); border-top-width: 1px; border-right-width: 1px; }

.scroll-indicator {
  position: absolute;
  right: var(--gutter);
  bottom: 2.5rem;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  color: var(--color-white);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  writing-mode: vertical-rl;
}
.scroll-line {
  width: 1px; height: 60px;
  background: rgba(255,255,255,0.4);
  position: relative;
  overflow: hidden;
}
.scroll-line::after {
  content: '';
  position: absolute;
  top: -100%; left: 0; right: 0;
  height: 100%;
  background: var(--color-white);
  animation: scrollLine 2.2s var(--ease-soft) infinite;
}
@keyframes scrollLine { to { top: 100%; } }

/* ---------- Hero highlights strip (reads as part of the hero, not a
   separate section — same dark background, no gap) ---------- */
.hero-highlights {
  background: var(--color-black);
  border-top: 1px solid rgba(247, 244, 238, 0.12);
}
/* Mobile keeps the exact same single-row concept as desktop — never a
   2x2 grid, never a resized-to-fit carousel. The row is simply wider than
   the viewport and scrolls horizontally, like the plans strip already
   does elsewhere on the site. */
.hero-highlights-grid {
  width: var(--container);
  margin: 0 auto;
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
}
.hero-highlights-grid::-webkit-scrollbar { display: none; }
.hero-highlight-card {
  flex: 0 0 auto;
  width: min(58vw, 230px);
  scroll-snap-align: start;
  padding: 1.5rem 1.25rem;
  border-right: 1px solid rgba(247, 244, 238, 0.1);
  transition: background-color var(--dur-base) var(--ease-out);
}
.hero-highlight-card:last-child { border-right: none; }
.hero-highlight-card:hover { background: rgba(247, 244, 238, 0.03); }
/* Numbered mark instead of a generic outline icon — reuses the same
   editorial numbering language as .section-num / .plan-num / the
   "Instante 00X" captions, so this reads as authored for the brand
   rather than a stock feature-grid icon set. */
.hero-highlight-icon {
  display: block;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.15rem;
  color: rgba(247, 244, 238, 0.55);
  margin-bottom: 0.85rem;
  transition: color var(--dur-base) var(--ease-out);
}
.hero-highlight-card:hover .hero-highlight-icon { color: var(--color-accent); }
.hero-highlight-card h3 {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 500;
  color: var(--color-white);
  font-size: 0.92rem;
  margin-bottom: 0.4rem;
}
.hero-highlight-card p {
  font-size: 0.74rem;
  line-height: 1.5;
  color: var(--color-gray-300);
}

@media (min-width: 900px) {
  .hero-highlights-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    overflow-x: visible;
    scroll-snap-type: none;
  }
  .hero-highlight-card {
    width: auto;
    padding: clamp(1.75rem, 4vw, 2.25rem) clamp(1.25rem, 3vw, 2rem);
  }
  .hero-highlight-icon { font-size: 1.35rem; }
  .hero-highlight-card h3 { font-size: clamp(0.98rem, 2vw, 1.1rem); }
  .hero-highlight-card p { font-size: 0.8rem; }
}

/* Mobile-only: 2x2 card grid, replacing the horizontal-scroll row above.
   Scoped entirely to max-width:899px so nothing here touches the desktop
   rules (or the >=900px block above) in any way — pure addition. */
@media (max-width: 899px) {
  .hero-highlights { padding: 25px 20px 24px; }
  .hero-highlights-grid {
    width: auto;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: repeat(2, 1fr);
    gap: 14px;
    overflow-x: visible;
    scroll-snap-type: none;
  }
  .hero-highlight-card {
    width: auto;
    height: 160px;
    padding: 18px 16px;
    border: 1px solid rgba(247, 244, 238, 0.1);
    border-radius: 18px;
    background: rgba(247, 244, 238, 0.03);
    overflow: hidden;
  }
  .hero-highlight-card:hover { background: rgba(247, 244, 238, 0.06); }
  .hero-highlight-icon { margin-bottom: 10px; }
  .hero-highlight-card h3 { margin-bottom: 6px; }
  .hero-highlight-card p {
    line-height: 1.45;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 1rem 2rem;
  border: 1px solid currentColor;
  border-radius: 999px;
  transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out);
}
/* One shared elevation language for every button — a small lift plus a
   soft contact shadow on hover, a quick settle-back on press. Subtle by
   design: 2px of movement, never a bounce. */
.btn:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); }
.btn:active { transform: translateY(0) scale(0.98); box-shadow: var(--shadow-xs); transition-duration: var(--dur-fast); }

.btn-outline { color: var(--color-white); }
.btn-outline:hover { background: var(--color-white); color: var(--color-black); }
.btn-solid { background: var(--color-black); color: var(--color-white); border-color: var(--color-black); }
.btn-solid:hover { background: transparent; color: var(--color-black); }
.btn-line { color: var(--color-ink); }
.btn-line:hover { background: var(--color-ink); color: var(--color-white); }

/* ==========================================================================
   Sections general
   ========================================================================== */
/* Vertical rhythm — each transition sized for what it's actually joining,
   not a single repeated value. Portfolio/Cinema stay close (both "look at
   the work"); Cinema/Plans tightened since the full-screen video already
   supplies its own pause; Plans/Story stays generous (commercial → personal
   is a real pivot); Story/Services/Testimonials sit close together (one
   flowing "who she is → what she offers → proof" cluster); Instagram/Contact
   stays the most generous gap on the page — the run-up to the final ask. */
.portfolio { padding-top: var(--space-standard); padding-bottom: var(--space-contained); padding-left: 0; padding-right: 0; }
.cinema { padding-top: var(--space-contained); padding-bottom: var(--space-contained); }
.plans { padding-top: var(--space-contained); padding-bottom: var(--space-standard); }
.story { padding-top: var(--space-standard); padding-bottom: var(--space-contained); }
.services { padding-top: var(--space-contained); padding-bottom: var(--space-contained); }
.testimonials { padding-top: var(--space-contained); padding-bottom: var(--space-standard); }
.instagram { padding-top: var(--space-contained); padding-bottom: var(--space-contained); }
.contact { padding-top: var(--space-generous); padding-bottom: var(--space-standard); }

.plans, .story, .services, .testimonials, .instagram, .contact {
  width: var(--container);
  margin: 0 auto;
}

.section-head { margin-bottom: clamp(2rem, 5vw, 4rem); max-width: 46ch; }
.section-num {
  display: inline-block;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  color: var(--color-accent-text);
  margin-bottom: 1rem;
}
.section-head h2 {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 5vw, 3.75rem);
  font-weight: 400;
  letter-spacing: -0.01em;
  margin-bottom: 1rem;
}
.section-lead { color: var(--color-gray-700); font-size: 1.05rem; max-width: 40ch; }

/* ---------- Manifesto ---------- */
.manifesto {
  padding: var(--space-generous) 0;
  width: var(--container);
  margin: 0 auto;
  text-align: center;
}
.manifesto-text {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 4.5vw, 3.5rem);
  line-height: 1.25;
  letter-spacing: -0.01em;
  max-width: 22ch;
  margin: 0 auto;
  /* Desktop keeps its current voice — italics are a mobile-only accent,
     enabled again inside the mobile media query below. */
  font-style: normal;
}
.manifesto-text em {
  font-style: normal;
}
.reveal-word { display: inline-block; opacity: 0.15; }

/* Mobile-only editorial rework of the manifesto — desktop is untouched
   above. Left-aligned, pulled up under the highlights band, tightened
   against the Portfolio head that follows it. */
@media (max-width: 560px) {
  .manifesto {
    text-align: left;
    padding: 2.5rem 0 0.75rem;
  }
  .manifesto::before {
    content: '';
    display: block;
    width: 32px;
    height: 1px;
    background: var(--color-accent-text);
    margin-bottom: 1.25rem;
  }
  .manifesto-text {
    font-size: 2.1rem;
    font-weight: 500;
    line-height: 1.22;
    max-width: 20ch;
    margin: 0;
  }
  .manifesto-text em { font-style: italic; }
  .portfolio { padding-top: 1.5rem; }
}

/* ==========================================================================
   Portfolio — vertical editorial storytelling (mobile-first)
   ========================================================================== */
.portfolio-head {
  width: var(--container);
  margin: 0 auto clamp(2.75rem, 10vw, 5.5rem);
  padding: 0 var(--gutter);
  max-width: 46ch;
}

.collection { margin-bottom: clamp(3.5rem, 14vw, 7.75rem); }
.collection:last-child { margin-bottom: 0; }

.collection-intro {
  width: var(--container);
  margin: 0 auto clamp(2.5rem, 11vw, 5rem);
  padding: 0 var(--gutter);
  max-width: 32ch;
}
.collection-kicker {
  display: block;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: 0.75rem;
  color: var(--color-accent-text);
  margin-bottom: 0.85rem;
}
.collection-title {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 500;
  font-size: clamp(2rem, 7vw, 3.25rem);
  line-height: 1.1;
  margin-bottom: 1rem;
}
.collection-desc { color: var(--color-gray-700); font-size: 1.02rem; }

.portfolio-photo {
  position: relative;
  width: 100%;
  height: 88svh;
  min-height: 460px;
  overflow: hidden;
  margin-bottom: clamp(2.75rem, 10vw, 5.5rem);
}
.portfolio-photo:last-child { margin-bottom: 0; }
.portfolio-photo img { width: 100%; height: 100%; object-fit: cover; }
.portfolio-photo--tall { height: 74svh; min-height: 400px; }

/* A paired moment for Colección 02 — the one collection that pauses on
   two images at once instead of the usual single-file rhythm. Stacks on
   mobile, sits side by side from tablet up. */
.portfolio-diptych {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.5rem, 4vw, 2rem);
  margin-bottom: clamp(2.75rem, 10vw, 5.5rem);
}
.portfolio-diptych .portfolio-photo {
  height: 70svh;
  min-height: 380px;
  margin-bottom: 0;
}

.portfolio-photo.has-caption::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(0deg, rgba(11,11,10,0.65) 0%, rgba(11,11,10,0) 40%);
  pointer-events: none;
}
.portfolio-caption {
  position: absolute;
  left: var(--gutter);
  bottom: clamp(1.5rem, 4vw, 2.5rem);
  z-index: 1;
  color: var(--color-white);
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.15rem, 3vw, 1.6rem);
}
.portfolio-caption em { font-style: normal; color: var(--color-accent); }

.portfolio-line {
  text-align: center;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.4rem, 5vw, 2.25rem);
  line-height: 1.3;
  max-width: 16ch;
  margin: 0 auto clamp(3.25rem, 12vw, 6.5rem);
  padding: 0 var(--gutter);
  color: var(--color-ink);
}

.portfolio-cta {
  text-align: center;
  color: var(--color-gray-700);
  font-size: 1rem;
  max-width: 32ch;
  margin: 0 auto;
  padding: 0 var(--gutter);
}
.portfolio-cta a { position: relative; padding-bottom: 2px; color: var(--color-ink); font-weight: 500; }

@media (min-width: 640px) {
  .portfolio-photo { height: 92svh; }
  .portfolio-photo--tall { height: 80svh; }
  .portfolio-diptych { grid-template-columns: 1fr 1fr; gap: var(--gutter); }
  .portfolio-diptych .portfolio-photo { height: 62svh; min-height: 360px; }
}

@media (min-width: 1024px) {
  .portfolio-photo { height: 100svh; margin-bottom: clamp(4.25rem, 8.5vw, 7rem); }
  .portfolio-photo--tall { height: 82svh; }
  .portfolio-diptych .portfolio-photo { height: 72svh; }
  .collection-intro, .portfolio-head { max-width: 40ch; }
}

/* Reframe fix — desktop only, scoped to the 9 Portfolio photos in the
   home's curated Colección 01/02/03 grid. On wide screens these
   full-bleed containers become much more landscape than the (portrait)
   source photos, so object-fit: cover was cropping out most of each
   composition to fill the width. Capping the container width and
   trimming its height brings the container's proportions closer to the
   photos' own, so cover has far less excess to cut away. object-position
   is tuned per photo so the main subject stays framed instead of
   defaulting to a dead-center crop. Nothing here touches mobile/tablet
   or any other section. */
@media (min-width: 1024px) {
  .portfolio-photo--reframed {
    max-width: var(--container);
    height: 82svh;
    margin-left: auto;
    margin-right: auto;
  }
  .portfolio-diptych { max-width: var(--container); margin-left: auto; margin-right: auto; }

  #pf-new-1 { object-position: center 30%; }
  #pf-new-2 { object-position: center 20%; }
  #pf-new-3 { object-position: center 25%; }
  #pf-new-4 { object-position: center 40%; }
  #pf-new-5 { object-position: center 20%; }
  #pf-new-6 { object-position: center 20%; }
  #pf-new-7 { object-position: center 30%; }
  #pf-new-8 { object-position: center 30%; }
  #pf-new-9 { object-position: center 20%; }
}

/* ==========================================================================
   Cinema — full-bleed video pause
   ========================================================================== */
.cinema {
  width: 100%;
  padding-left: 0;
  padding-right: 0;
  /* .cinema-frame scales in on entrance via GSAP; its own overflow:hidden
     can't clip its own transformed box, so the parent needs to. Otherwise
     it leaks a few px past the viewport edge on wide screens pre-reveal. */
  overflow-x: hidden;
}
.cinema-frame {
  position: relative;
  width: 100%;
  /* The one section that breaks the site's steady rhythm — a near-full-
     screen, immersive pause instead of another boxed content block. */
  height: clamp(520px, 92vh, 920px);
  overflow: hidden;
  background: var(--color-black);
}
.cinema-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* Mobile: fill edge-to-edge (cover) — no letterboxing, matches the
     portrait source almost exactly. Wider frames switch to "contain"
     below so a portrait video doesn't get cropped to a sliver. */
  object-fit: cover;
  object-position: center;
}

@media (min-width: 768px) {
  .cinema-video { object-fit: contain; }
}
.cinema-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(11, 11, 10, 0.28) 0%, rgba(11, 11, 10, 0) 30%, rgba(11, 11, 10, 0.6) 100%);
  pointer-events: none;
}
.cinema-kicker {
  position: absolute;
  left: var(--gutter);
  top: clamp(1.5rem, 4vw, 2.25rem);
  z-index: 2;
  color: var(--color-white);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.cinema-sound {
  position: absolute;
  right: clamp(1rem, 3vw, 1.5rem);
  bottom: clamp(1rem, 3vw, 1.5rem);
  z-index: 2;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid rgba(247, 244, 238, 0.5);
  background: rgba(11, 11, 10, 0.35);
  color: var(--color-white);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: border-color var(--dur-base) var(--ease-out), background-color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.cinema-sound:hover, .cinema-sound:focus-visible {
  border-color: var(--color-white);
  background: rgba(11, 11, 10, 0.55);
}
.cinema-sound-icon { display: flex; }
.cinema-sound-icon svg { display: block; }
.cinema-sound-icon .icon-on { display: none; }
.cinema-sound.is-active .icon-on { display: block; }
.cinema-sound.is-active .icon-off { display: none; }

/* ---------- Accessible but visually hidden text ---------- */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Whispered over the footage itself instead of explained in a paragraph
   below it — the frame becomes one uninterrupted moment. */
.cinema-caption {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: clamp(1.5rem, 4vw, 2.25rem);
  z-index: 2;
  max-width: 34ch;
  color: var(--color-white);
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.05rem, 2.2vw, 1.4rem);
  line-height: 1.4;
  pointer-events: none;
}

/* ==========================================================================
   Plans — premium pricing cards
   Mobile/tablet: horizontal scroll-snap strip (all three reachable in one
   place, never stacked). Desktop: static 3-column grid.
   ========================================================================== */
.plans-scroll {
  position: relative;
  margin: 0 calc(var(--gutter) * -1);
}
.plans-grid {
  display: flex;
  gap: clamp(0.75rem, 2.5vw, 1.25rem);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-left: var(--gutter);
  padding: 0.5rem var(--gutter) 1rem;
  scrollbar-width: none;
}
.plans-grid::-webkit-scrollbar { display: none; }

/* Soft edge fade hints that there's more to scroll (mobile/tablet) */
.plans-scroll::before,
.plans-scroll::after {
  content: '';
  position: absolute;
  top: 0; bottom: 1rem;
  width: clamp(1rem, 5vw, 2.5rem);
  z-index: 2;
  pointer-events: none;
}
.plans-scroll::before { left: 0; background: linear-gradient(90deg, var(--color-white), transparent); }
.plans-scroll::after { right: 0; background: linear-gradient(270deg, var(--color-white), transparent); }

.plan-card {
  position: relative;
  flex: 0 0 auto;
  /* ~20.8% smaller than the original 340px cap (12%, then another 10% on
     top, per request) — layout mechanism (flex/scroll-snap/grid)
     untouched, only the card's own dimensions shrink. */
  width: min(calc((100vw - 2 * var(--gutter)) * 0.792), 269px);
  scroll-snap-align: center;
  scroll-snap-stop: always;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--color-gray-300);
  border-radius: 13px;
  overflow: hidden;
  transition: transform var(--dur-slow) var(--ease-out), box-shadow var(--dur-slow) var(--ease-out), border-color var(--dur-slow) var(--ease-out);
}
.plan-card:hover {
  transform: translateY(-8px);
  box-shadow: var(--shadow-lg);
  border-color: var(--color-ink);
}
.plan-card:active {
  transform: translateY(-3px);
  transition-duration: var(--dur-fast);
}
.plan-card--featured {
  border-color: var(--color-ink);
  background: var(--color-paper);
}

.plan-card-media {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--color-black);
}
.plan-card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
.plan-card:hover .plan-card-media img { transform: scale(1.06); }
.plan-card-media::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(0deg, rgba(11, 11, 10, 0.55) 0%, rgba(11, 11, 10, 0) 45%);
  pointer-events: none;
}
.plan-num {
  position: absolute;
  z-index: 1;
  bottom: 0.51rem;
  right: 0.68rem;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.19rem, 2.8vw, 1.47rem);
  line-height: 1;
  color: var(--color-white);
}
.plan-card--featured .plan-num { color: var(--color-accent); }
.plan-ribbon {
  display: block;
  text-align: center;
  font-size: 0.51rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  padding: 0.48rem 0 0.28rem;
}

.plan-card-body {
  display: flex;
  flex-direction: column;
  gap: 0.51rem;
  padding: clamp(0.71rem, 1.89vw, 0.91rem) clamp(0.79rem, 2vw, 0.99rem) clamp(0.79rem, 1.89vw, 0.95rem);
  flex: 1;
}
.plan-card-head { display: flex; flex-direction: column; gap: 0.28rem; }
.plan-name {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 500;
  font-size: clamp(0.95rem, 2vw, 1.15rem);
}
.plan-desc { color: var(--color-gray-700); font-size: 0.62rem; line-height: 1.45; }
.plan-fit {
  color: var(--color-gray-500);
  font-size: 0.57rem;
  line-height: 1.4;
}
.plan-price {
  display: flex;
  align-items: baseline;
  gap: 0.36rem;
  flex-wrap: wrap;
  padding-top: 0.4rem;
  border-top: 1px solid var(--color-gray-300);
}
.plan-price-amount { font-family: var(--font-display); font-weight: 500; font-size: clamp(0.91rem, 1.75vw, 1.07rem); }
.plan-price-unit { font-size: 0.54rem; color: var(--color-gray-500); }
.plan-features { display: flex; flex-direction: column; gap: 0.32rem; }
.plan-features li {
  display: flex;
  align-items: center;
  gap: 0.43rem;
  font-size: 0.6rem;
  color: var(--color-gray-700);
}
.plan-feature-icon { flex-shrink: 0; width: 11px; height: 11px; color: var(--color-gray-500); }
.plan-card--featured .plan-feature-icon { color: var(--color-accent-text); }
.plan-cta { align-self: stretch; justify-content: center; margin-top: auto; padding: 0.4rem 0.99rem; font-size: 0.52rem; }

.plans-dots {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 1.5rem;
}
.plans-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-gray-300);
  transition: background-color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.plans-dot.is-active { background: var(--color-ink); transform: scale(1.35); }

.plans-note {
  margin-top: clamp(2rem, 5vw, 3rem);
  text-align: center;
  color: var(--color-gray-500);
  font-size: 0.85rem;
}
.plans-note a { position: relative; padding-bottom: 2px; }

@media (min-width: 1024px) {
  .plans-scroll { margin: 0; }
  .plans-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    align-items: stretch;
    overflow: visible;
    scroll-snap-type: none;
    max-width: 744px;
    margin: 0 auto;
    padding: 0.5rem 0 1rem;
  }
  .plan-card { width: auto; }
  .plan-card--featured { margin-top: -0.59rem; }
  .plan-card--featured .plan-card-body {
    padding-top: clamp(1.11rem, 2.38vw, 1.39rem);
    padding-bottom: clamp(1.27rem, 2.8vw, 1.58rem);
  }
  .plans-scroll::before, .plans-scroll::after { display: none; }
  .plans-dots { display: none; }
}

/* ==========================================================================
   Story — same light background as the rest of the page (no more dark
   full-bleed break). Structure/grid unchanged, only color.
   ========================================================================== */
.story {
  position: relative;
  color: var(--color-ink);
}
.story::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  left: 50%;
  width: 100vw;
  transform: translateX(-50%);
  background: var(--color-white);
  z-index: -1;
}
.story-block {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 6rem);
  align-items: center;
  margin-bottom: clamp(2.25rem, 6vw, 5rem);
}
.story-block:last-child { margin-bottom: 0; }
.story-block.reverse { direction: rtl; }
.story-block.reverse > * { direction: ltr; }
.story-media { aspect-ratio: 4/5; overflow: hidden; }
.story-media img { width: 100%; height: 100%; object-fit: cover; }
.story-kicker {
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: 0.75rem;
  color: var(--color-accent-text);
  margin-bottom: 1.25rem;
}
.story-quote {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.4rem, 2.4vw, 2rem);
  line-height: 1.35;
  margin-bottom: 1.5rem;
}
.story-body { color: var(--color-gray-700); max-width: 44ch; font-size: 1rem; }

/* ==========================================================================
   Services
   ========================================================================== */
/* Home — featured services (curated teaser, full catalog lives on
   servicios.html). Editorial alternating rows instead of a uniform card
   grid — reuses the same left/right RTL technique as .story-block (§Story)
   and the same hover-arrow link as .service-editorial-link (§catalog), so
   this reads as the site's own established language recombined, not a
   third, unrelated card pattern. */
.services-editorial-list {
  display: flex;
  flex-direction: column;
  gap: clamp(3rem, 7vw, 5.5rem);
}
.service-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
}
.service-row.reverse { direction: rtl; }
.service-row.reverse > * { direction: ltr; }
.service-row-media {
  display: block;
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  transition: box-shadow var(--dur-slow) var(--ease-out);
}
.service-row-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
.service-row:hover .service-row-media { box-shadow: var(--shadow-md); }
.service-row:hover .service-row-media img { transform: scale(1.05); }
.service-row-media { transition: transform var(--dur-fast) var(--ease-out); }
.service-row-media:active { transform: scale(0.985); }
.service-row-num {
  display: block;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1rem;
  letter-spacing: 0.05em;
  color: var(--color-accent-text);
  margin-bottom: 0.75rem;
}
.service-row-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2rem, 5vw, 3.4rem);
  line-height: 1.05;
  margin-bottom: 0.9rem;
}
.service-row-title a {
  color: inherit;
  text-decoration: none;
  transition: color var(--dur-base) var(--ease-out);
}
.service-row:hover .service-row-title a { color: var(--color-accent-text); }
.service-row-desc { color: var(--color-gray-700); font-size: 1rem; line-height: 1.6; max-width: 38ch; margin-bottom: 1.25rem; }
.service-row-link {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  color: var(--color-ink);
  text-decoration: none;
}
.service-row-link::after {
  content: '';
  width: 16px;
  height: 1px;
  background: currentColor;
  transition: width var(--dur-base) var(--ease-out);
}
.service-row:hover .service-row-link::after { width: 26px; }

@media (max-width: 860px) {
  .service-row, .service-row.reverse { grid-template-columns: 1fr; direction: ltr; }
  .service-row-media { order: -1; }
}

.services-cta-wrap { text-align: center; margin-top: clamp(2.75rem, 6vw, 4rem); }

/* Services catalog page (servicios.html) — editorial intro above the
   editorial card grid. */
.services-intro { width: var(--container); margin: 0 auto; padding-top: clamp(7rem, 14vw, 9rem); padding-bottom: var(--space-contained); }
.services-intro-inner { max-width: 56ch; }
.services-intro-inner h1 {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 6vw, 4.25rem);
  font-weight: 400;
  letter-spacing: -0.01em;
  margin-bottom: 1rem;
}
.services-back-link {
  display: inline-block;
  margin-bottom: clamp(1.5rem, 4vw, 2.5rem);
  font-size: 0.85rem;
  color: var(--color-gray-700);
  text-decoration: none;
  border-bottom: 1px solid var(--color-gray-300);
  transition: color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}
.services-back-link:hover { color: var(--color-ink); border-color: var(--color-ink); }

/* Circular icon-only back button for the Servicios/Catálogo page — same
   42px size and left-arrow SVG already used by .service-back-circle on
   the individual service pages, but tuned for this section's light
   background instead of a dark photo overlay: ink-colored border/icon
   on cream rather than translucent white-on-black. */
.services-back-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  margin-bottom: clamp(1.5rem, 4vw, 2.5rem);
  border-radius: 50%;
  border: 1px solid var(--color-gray-300);
  color: var(--color-ink);
  transition: background-color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.services-back-circle svg { width: 16px; height: 16px; display: block; transition: transform var(--dur-base) var(--ease-out); }
.services-back-circle:hover,
.services-back-circle:focus-visible {
  background: var(--color-gray-300);
  border-color: var(--color-ink);
}
.services-back-circle:hover svg,
.services-back-circle:focus-visible svg { transform: translateX(-3px); }

/* Circular icon-only back button — reuses the exact same translucent
   white-on-photo treatment already established by .lightbox-close/
   .lightbox-arrow, so it reads as native to the design rather than a
   bolted-on control. Only used in .service-hero-content (dark photo
   overlay); .services-back-link elsewhere keeps its original text style. */
.service-back-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  margin-bottom: clamp(1.5rem, 4vw, 2.5rem);
  border-radius: 50%;
  background: rgba(247, 244, 238, 0.06);
  border: 1px solid rgba(247, 244, 238, 0.15);
  color: var(--color-white);
  transition: background-color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
  /* Plain <a href> to a real URL — no JS involved, so it works identically
     on touch as it does with a mouse. touch-action skips the ~300ms
     tap-delay some mobile browsers add while waiting to see if a second
     tap is coming; tap-highlight-color swaps the default gray flash for
     the same hover treatment already defined below, so touch and mouse
     feel like the same control. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.service-back-circle svg { width: 16px; height: 16px; transition: transform var(--dur-base) var(--ease-out); }
.service-back-circle:hover,
.service-back-circle:focus-visible {
  background: rgba(247, 244, 238, 0.14);
  border-color: rgba(247, 244, 238, 0.3);
}
.service-back-circle:hover svg,
.service-back-circle:focus-visible svg { transform: translateX(-3px); }

/* Editorial card grid — the layout adapts to any number of services with
   no breakpoint edits: auto-fill keeps generating columns as space allows,
   each card is a fixed 320px-minimum unit, and it reflows to a single
   column once the viewport can't fit two side by side. Adding a service is
   just adding one more .service-editorial-card block. */
.services-editorial-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
  gap: clamp(2.5rem, 5vw, 3.5rem) clamp(1.75rem, 4vw, 3rem);
}
.service-editorial-card { display: flex; flex-direction: column; transition: transform var(--dur-slow) var(--ease-out); }
.service-editorial-card:hover { transform: translateY(-4px); }
.service-editorial-card:active { transform: translateY(-1px); transition-duration: var(--dur-fast); }
.service-editorial-media {
  display: block;
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  margin-bottom: 1.25rem;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  transition: box-shadow var(--dur-slow) var(--ease-out);
}
.service-editorial-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
.service-editorial-card:hover .service-editorial-media { box-shadow: var(--shadow-md); }
.service-editorial-card:hover .service-editorial-media img { transform: scale(1.06); }
.service-editorial-index { display: block; font-size: 0.75rem; letter-spacing: 0.1em; color: var(--color-accent-text); margin-bottom: 0.6rem; }
.service-editorial-title { font-family: var(--font-display); font-weight: 400; font-size: clamp(1.3rem, 2.2vw, 1.7rem); margin-bottom: 0.5rem; }
.service-editorial-desc { color: var(--color-gray-700); font-size: 0.9rem; line-height: 1.55; max-width: 36ch; margin-bottom: 1.1rem; }
.service-editorial-link {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.82rem;
  letter-spacing: 0.03em;
  color: var(--color-ink);
  text-decoration: none;
}
.service-editorial-link::after {
  content: '';
  width: 16px;
  height: 1px;
  background: currentColor;
  transition: width var(--dur-base) var(--ease-out);
}
.service-editorial-card:hover .service-editorial-link::after { width: 26px; }

/* ==========================================================================
   Service detail pages (generated by build.js from data/services.js) +
   Portfolio category pages — shared components, one definition reused by
   every generated page regardless of how many services/categories exist.
   ========================================================================== */

/* ---------- Service hero ---------- */
.service-hero {
  position: relative;
  height: clamp(420px, 58vh, 640px);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
}
.service-hero-media { position: absolute; inset: 0; }
.service-hero-media img { width: 100%; height: 100%; object-fit: cover; }
.service-hero-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(11,11,10,0.1) 0%, rgba(11,11,10,0.78) 100%);
}
.service-hero-content {
  position: relative;
  z-index: 1;
  width: var(--container);
  margin: 0 auto;
  padding-bottom: clamp(2.25rem, 6vw, 4rem);
  color: var(--color-white);
}
.service-hero-content h1 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.5rem, 6vw, 4.5rem);
  letter-spacing: -0.01em;
  margin: 0.75rem 0 0.5rem;
}
.service-hero-tagline { font-size: 1.05rem; color: rgba(247,244,238,0.88); max-width: 42ch; margin-bottom: 1.5rem; }

/* ---------- Description ---------- */
.service-description {
  width: var(--container);
  max-width: 68ch;
  margin: 0 auto;
  padding: var(--space-contained) 0;
}
/* Photo-first: the description is one short paragraph. line-clamp is a
   hard ceiling (5 lines desktop, ~3-4 on the narrower mobile column at a
   smaller size) so text can never balloon into a block that competes
   with the gallery below it. */
.service-description p {
  font-size: 1.05rem;
  line-height: 1.7;
  color: var(--color-gray-700);
  display: -webkit-box;
  -webkit-line-clamp: 5;
  line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
@media (max-width: 560px) {
  .service-description p { font-size: 0.95rem; line-height: 1.6; }
}

/* ---------- Editorial gallery (shared by service pages + portfolio categories) ---------- */
.service-gallery-section,
.portfolio-category {
  width: var(--container);
  margin: 0 auto;
  padding-bottom: var(--space-contained);
}
.portfolio-category { padding-top: var(--space-contained); }

.gallery-editorial { display: flex; flex-direction: column; }
.gallery-batch { display: flex; flex-direction: column; }
/* Without this, the class rule above (author stylesheet) wins the cascade
   tie against the browser's built-in `[hidden] { display: none }` (same
   specificity, author origin always wins) — every batch after the first
   would render immediately regardless of its `hidden` attribute, making
   "Cargar más" look broken: all photos already visible, button does
   nothing when clicked. */
.gallery-batch[hidden] { display: none; }
.gallery-batch + .gallery-batch { margin-top: clamp(2.25rem, 5vw, 3.5rem); }
.gallery-pattern { display: grid; gap: clamp(1rem, 2.5vw, 1.5rem); }
/* Skeleton loader: a soft shimmer sits under every photo until it has
   actually decoded (JS toggles .is-loaded via IntersectionObserver + the
   image's own load event — see main.js). Loading="lazy" still owns the
   fetch-timing decision; this only owns the reveal. */
.gallery-photo {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: linear-gradient(100deg, var(--color-gray-300) 30%, var(--color-paper) 50%, var(--color-gray-300) 70%);
  background-size: 200% 100%;
  animation: gallerySkeleton 1.6s ease-in-out infinite;
}
.gallery-photo.is-loaded { animation: none; background: none; }
.gallery-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
  /* Without this, the browser's native "drag this image" gesture can hijack
     a touch/trackpad swipe that starts on a photo, making the page feel
     stuck instead of scrolling — the same fix already applied to
     .lightbox-image, just missing here on the grid thumbnails. */
  user-select: none;
  -webkit-user-drag: none;
}
.gallery-photo.is-loaded img { opacity: 1; }
/* The custom cursor already signals "clickable" on fine-pointer devices
   (data-hover grows the ring) — this is the same cue for everyone else:
   touch, keyboard focus, reduced-motion-safe. Same 1.05 scale used by
   every other card image on the site, so a gallery grid never reads as a
   less-designed component than the rest of the page. */
.gallery-photo:hover img,
.gallery-photo:focus-visible img { transform: scale(1.05); }
.gallery-photo:active img { transform: scale(1.02); transition-duration: var(--dur-fast); }

/* Video tiles are a poster <img> plus this one extra affordance — the
   actual clip only loads once the lightbox opens (see gallery-photo--video
   in galleryGrid.js and the video branch in lightbox.js). */
.gallery-play-icon {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 52px; height: 52px;
  border-radius: 50%;
  background: rgba(11, 11, 10, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-white);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-out), background-color var(--dur-base) var(--ease-out);
  pointer-events: none;
}
.gallery-play-icon svg { width: 20px; height: 20px; margin-left: 2px; }
.gallery-photo--video:hover .gallery-play-icon { transform: translate(-50%, -50%) scale(1.08); background: rgba(11, 11, 10, 0.75); }

@keyframes gallerySkeleton {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .gallery-photo { animation: none; }
}

/* Rhythm, not a uniform gap: a full-bleed single earns a generous pause
   after it (a breath before the next moment); the dense 4-grid stays
   tight (it already reads as a quicker, busier beat). b/c sit at a
   medium default. Deliberately not scoped to any one collection — this
   is what makes every category's pacing feel considered without any
   category-specific CSS. */
.gallery-pattern { margin-bottom: clamp(2.25rem, 5vw, 3.5rem); }
.gallery-pattern:last-child { margin-bottom: 0; }
.gallery-pattern-a { margin-bottom: clamp(3.5rem, 8vw, 6rem); }
.gallery-pattern-d { margin-bottom: clamp(1.5rem, 3.5vw, 2.5rem); }

/* a — full-bleed single */
.gallery-pattern-a { grid-template-columns: 1fr; }

/* b — tall diptych */
.gallery-pattern-b { grid-template-columns: 1fr; }
@media (min-width: 640px) {
  .gallery-pattern-b { grid-template-columns: 1fr 1fr; }
}

/* c — offset triptych: one wide top, two below */
.gallery-pattern-c { grid-template-columns: 1fr; }
@media (min-width: 640px) {
  .gallery-pattern-c { grid-template-columns: repeat(2, 1fr); }
  .gallery-pattern-c .gallery-photo:first-child { grid-column: 1 / -1; }
}

/* d — dense grid of four */
.gallery-pattern-d { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 900px) {
  .gallery-pattern-d { grid-template-columns: repeat(4, 1fr); }
}

.gallery-load-more-wrap { text-align: center; margin-top: clamp(1.5rem, 4vw, 2.5rem); }
.gallery-load-more [data-gallery-remaining] { opacity: 0.6; font-size: 0.85em; }

.gallery-photo { cursor: pointer; }
html.has-custom-cursor .gallery-photo { cursor: none; }

/* ---------- Lightbox ---------- */
/* Below .grain/.cursor (9999/9998 — both pointer-events:none, meant to sit
   over literally everything including this) and above every other layer
   on the site (header/whatsapp-float top out around 1200). */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 9990;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-slow) var(--ease-out), visibility 0s linear var(--dur-slow);
}
.lightbox.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--dur-slow) var(--ease-out);
}
/* Explicit layers, not implicit DOM-order stacking — the stage fills the
   same 100%/100% box as the backdrop and controls, so without an explicit
   z-index here the stage (later in the DOM) paints and hit-tests *above*
   the close button, arrows, and backdrop, silently swallowing every click
   meant for them. Root cause of "close/arrows don't respond" — fixed at
   the layer, not per-button. */
.lightbox-backdrop {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: rgba(11, 11, 10, 0.96);
}
.lightbox-stage {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  touch-action: none;
}
.lightbox-image {
  max-width: min(94vw, 1600px);
  max-height: 88vh;
  object-fit: contain;
  touch-action: none;
  user-select: none;
  -webkit-user-drag: none;
  will-change: transform;
  box-shadow: 0 40px 100px rgba(0, 0, 0, 0.5);
}
/* No CSS transition on the image itself — dragging needs 1:1 tracking.
   .is-settling is toggled by JS only around the snap-back/close/navigate
   moments, so the deliberate motion still uses the site's own easing. */
.lightbox-image.is-settling {
  transition: transform var(--dur-slow) var(--ease-out);
}

/* Video items skip all the custom pan/zoom/swipe gesture code (see
   isVideo() guards in lightbox.js) and just use the native player, so this
   needs its own touch-action — the stage's touch-action:none (required for
   the image's pinch/pan/swipe tracking) would otherwise also block taps on
   this element's own controls (play, scrub, volume). */
.lightbox-video {
  display: none;
  max-width: min(94vw, 1600px);
  max-height: 88vh;
  touch-action: auto;
  box-shadow: 0 40px 100px rgba(0, 0, 0, 0.5);
}

.lightbox-close,
.lightbox-arrow {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(247, 244, 238, 0.06);
  border: 1px solid rgba(247, 244, 238, 0.15);
  border-radius: 50%;
  color: var(--color-white);
  touch-action: manipulation;
  transition: background-color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
.lightbox-close:hover,
.lightbox-arrow:hover { background: rgba(247, 244, 238, 0.14); border-color: rgba(247, 244, 238, 0.3); }

.lightbox-close {
  top: clamp(1rem, 3vw, 1.75rem);
  right: clamp(1rem, 3vw, 1.75rem);
  width: 38px;
  height: 38px;
}
.lightbox-close-icon { position: relative; width: 13px; height: 13px; }
.lightbox-close-icon::before,
.lightbox-close-icon::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
}
.lightbox-close-icon::before { transform: rotate(45deg); }
.lightbox-close-icon::after { transform: rotate(-45deg); }

.lightbox-arrow {
  top: 50%;
  transform: translateY(-50%);
  width: 46px;
  height: 46px;
}
.lightbox-arrow svg { width: 16px; height: 16px; }
.lightbox-arrow-prev { left: clamp(0.75rem, 2.5vw, 2rem); }
.lightbox-arrow-next { right: clamp(0.75rem, 2.5vw, 2rem); }
.lightbox-arrow[disabled] { opacity: 0; pointer-events: none; }
@media (max-width: 720px) {
  .lightbox-arrow { display: none; }
}

.lightbox-counter {
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: clamp(1rem, 3vw, 1.75rem);
  transform: translateX(-50%);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  color: rgba(247, 244, 238, 0.6);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

/* ---------- Book CTA band ---------- */
.service-book {
  width: var(--container);
  margin: 0 auto;
  padding: var(--space-contained) 0;
  text-align: center;
}
.service-book h2 { font-family: var(--font-display); font-weight: 400; font-size: clamp(1.6rem, 3vw, 2.25rem); max-width: 30ch; margin: 0 auto 1.5rem; }

/* ==========================================================================
   Testimonials
   ========================================================================== */
.testimonials-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(2rem, 4vw, 3rem);
}
.testimonial {
  position: relative;
  border-top: 1px solid var(--color-gray-300);
  padding-top: 1.75rem;
  transition: transform var(--dur-slow) var(--ease-out), border-color var(--dur-slow) var(--ease-out), box-shadow var(--dur-slow) var(--ease-out);
}
.testimonial:hover {
  transform: translateY(-8px);
  border-color: var(--color-ink);
  box-shadow: var(--shadow-lg);
}
.testimonial:active {
  transform: translateY(-3px);
  transition-duration: var(--dur-fast);
}
@media (min-width: 1025px) {
  /* Slight editorial stagger instead of a flat, uniform 3-up grid */
  .testimonial:nth-child(2) { margin-top: clamp(2rem, 4vw, 3.25rem); }
  .testimonial:nth-child(3) { margin-top: clamp(0.75rem, 1.5vw, 1.25rem); }
}
.testimonial::before {
  content: '"';
  display: block;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 3.5rem;
  line-height: 1;
  color: var(--color-accent-text);
  margin-bottom: 0.5rem;
  opacity: 0.7;
}
.testimonial p {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.15rem;
  line-height: 1.5;
  margin-bottom: 1.5rem;
}
.testimonial cite {
  font-style: normal;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-gray-500);
}

/* ==========================================================================
   Instagram
   ========================================================================== */
.instagram-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: clamp(2rem, 5vw, 3.5rem);
  flex-wrap: wrap;
  gap: 1.5rem;
}
.instagram-head h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.25rem, 5vw, 3.75rem);
  letter-spacing: -0.01em;
}
.instagram-marquee {
  overflow: hidden;
}
.instagram-strip {
  display: flex;
  gap: clamp(0.75rem, 1.5vw, 1.5rem);
  width: max-content;
  animation: marqueeScroll 38s linear infinite;
}
.instagram-marquee:hover .instagram-strip,
.instagram-marquee:focus-within .instagram-strip { animation-play-state: paused; }
.ig-item {
  flex: 0 0 auto;
  width: clamp(200px, 20vw, 300px);
  aspect-ratio: 4/5;
  overflow: hidden;
  position: relative;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-xs);
}
.ig-item img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slow) var(--ease-out); }
.ig-item:hover img { transform: scale(1.05); }
.instagram-marquee::-webkit-scrollbar { height: 3px; }
.instagram-marquee::-webkit-scrollbar-thumb { background: var(--color-gray-300); }

/* ==========================================================================
   Contact
   ========================================================================== */
.contact {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2.5rem, 6vw, 6rem);
}
.contact-info h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2rem, 4vw, 3rem);
  line-height: 1.15;
  margin: 1rem 0 1.25rem;
}
.contact-info h2 em { font-style: italic; color: var(--color-accent-text); }
.contact-info > p { color: var(--color-gray-700); max-width: 38ch; margin-bottom: 2.25rem; }
.contact-details { display: flex; flex-direction: column; gap: 0.85rem; }
.contact-details a { position: relative; padding-bottom: 2px; }
.contact-social-link { display: inline-flex; align-items: center; gap: 0.5rem; }
.contact-social-icon { width: 18px; height: 18px; flex-shrink: 0; }

.contact-form { display: flex; flex-direction: column; gap: 1.5rem; }
.form-row { display: flex; flex-direction: column; gap: 0.5rem; }
.form-row label {
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-gray-500);
}
/* A quiet echo of the numbering used everywhere else on the site (section
   heads, plan cards) — makes the form read as another authored piece of
   the page, not a bolted-on utility. */
.form-row-num {
  color: var(--color-accent-text);
  letter-spacing: 0.1em;
  margin-right: 0.6em;
}
.form-row input, .form-row select, .form-row textarea {
  border-bottom: 1px solid var(--color-gray-300);
  padding: 0.6rem 0.1rem;
  font-family: var(--font-display);
  font-size: 1.15rem;
  transition: border-color var(--dur-fast) var(--ease-out);
  resize: vertical;
}
.form-row input::placeholder, .form-row textarea::placeholder {
  color: var(--color-gray-500);
  font-style: italic;
  opacity: 1;
}
.form-row input:focus, .form-row select:focus, .form-row textarea:focus {
  border-color: var(--color-accent-text);
}
.form-row select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding-right: 1.5rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23524c40' stroke-width='1.3'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.15rem center;
  background-size: 12px;
}
.contact-form .btn { margin-top: 0.5rem; align-self: flex-start; }
.form-note { font-size: 0.85rem; color: var(--color-accent-text); min-height: 1.2em; }

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer {
  background: var(--color-black);
  color: var(--color-white);
  padding: clamp(2.5rem, 5vw, 4rem) 0 2rem;
  overflow: hidden;
}
.footer-marquee {
  display: flex;
  width: max-content;
  white-space: nowrap;
  margin-bottom: clamp(1.75rem, 5vw, 3.25rem);
  animation: marqueeScroll 26s linear infinite;
}
.site-footer:hover .footer-marquee { animation-play-state: paused; }
.footer-marquee span {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(3rem, 10vw, 7rem);
  color: transparent;
  -webkit-text-stroke: 1px rgba(247, 244, 238, 0.35);
  padding-right: 1.5rem;
}

@keyframes marqueeScroll {
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .instagram-strip, .footer-marquee { animation: none !important; }
}
.footer-top, .footer-bottom, .footer-cta {
  width: var(--container);
  margin-left: auto;
  margin-right: auto;
}
.footer-top, .footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
}
.footer-top {
  padding-bottom: clamp(1.75rem, 4.5vw, 3rem);
  border-bottom: 1px solid rgba(255,255,255,0.15);
  margin-bottom: 1.75rem;
}
.footer-logo {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.75rem, 4vw, 2.5rem);
}
.footer-top-link { position: relative; padding-bottom: 2px; font-size: 0.8rem; letter-spacing: 0.06em; text-transform: uppercase; }
.footer-cta {
  font-size: 0.95rem;
  color: var(--color-gray-300);
  margin-bottom: 1.75rem;
}
.footer-cta a { position: relative; padding-bottom: 2px; color: var(--color-white); font-family: var(--font-display); }
.footer-bottom { font-size: 0.75rem; color: var(--color-gray-300); }
.footer-bottom nav { display: flex; gap: 1.5rem; }
.footer-bottom nav a { position: relative; padding-bottom: 2px; }
.footer-bottom nav a:hover { color: var(--color-white); }

/* ==========================================================================
   Scroll reveal base states (animated via JS/GSAP)
   ========================================================================== */
.reveal-up { opacity: 0; transform: translateY(28px); }

/* Mobile motion is even more restrained than desktop — same language,
   smaller distance, so entrances never feel like they're overshooting a
   small viewport. */
@media (max-width: 640px) {
  .reveal-up { transform: translateY(16px); }
}

/* ---------- Magnetic elements ---------- */
/* Targets [data-magnetic] directly — these are the elements the pointer
   rAF loop in main.js actually applies an inline transform to. */
[data-magnetic] { will-change: transform; }

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 1024px) {
  .nav-desktop { display: none; }
  .menu-toggle { display: block; }
  .contact { grid-template-columns: 1fr; }
  .testimonials-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 860px) {
  .story-block, .story-block.reverse { grid-template-columns: 1fr; direction: ltr; }
  .story-media { order: -1; }
  .testimonials-grid { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  :root { --header-h: 72px; }
  /* Bottom-anchored, not clustered under the name badge: pushes the whole
     block (title, actions) down so the model's face has the top of the
     frame to itself. flex-end + a fixed 28px bottom padding on
     .hero-content (whose last child is .hero-actions) is what guarantees
     the buttons sit a controlled 24-32px above the hero's bottom edge
     without ever touching it. Title size/typography unchanged — only the
     vertical position moved. */
  .hero { justify-content: flex-end; }
  .hero-content { padding: 0 0 28px; }
  .hero-title { font-size: clamp(2.9rem, 13.5vw, 4.05rem); }
  /* The original overlay was tuned for bottom-anchored text over a dark
     part of the photo. Now the text block sits higher, over a much
     lighter area (the coat), so it needs its own darkening here. */
  .hero-overlay {
    background: linear-gradient(180deg, rgba(11,11,10,0.55) 0%, rgba(11,11,10,0.4) 45%, rgba(11,11,10,0.15) 65%, rgba(11,11,10,0.7) 100%);
  }
  .scroll-indicator { display: none; }
  .hero-frame { display: none; }
  .btn { padding: 0.9rem 1.6rem; width: 100%; justify-content: center; }
  .contact-form .btn { width: auto; align-self: stretch; }
  /* .hero-actions .btn's own specificity otherwise wins over the generic
     .btn rule above even here — without this override the hero CTAs stay
     at their compact ~31px height, the smallest tap target on the whole
     site, on the one button a first-time visitor is most likely to press. */
  .hero-actions .btn { padding: 0.85rem 1.1rem; font-size: 0.68rem; }
  .ig-item { width: 65vw; }

  /* Compact "Hablemos de tu próxima sesión" ~20-25% shorter on mobile.
     Only spacing (padding/gap/margin) changes here — no font-size, color,
     icon, or structural change. Desktop keeps the base rules above untouched.
     Measured in-browser at 375px: 1110px -> 875px, a 21% reduction, with
     zero overlap and the CTA button still fully inside the section. */
  .contact { padding-top: 2.75rem; padding-bottom: 2.25rem; gap: 1.5rem; }
  .contact-info h2 { margin: 0.5rem 0 0.6rem; }
  .contact-info > p { margin-bottom: 1rem; }
  .contact-details { gap: 0.5rem; }
  .contact-form { gap: 0.75rem; }
  .form-row { gap: 0.25rem; }
  .form-row input, .form-row select, .form-row textarea { padding: 0.35rem 0.1rem; }
  .contact-form .btn { margin-top: 0.25rem; }
}
