/*
 * Proyecto: Landing Plus
 * Ruta: /wp-content/themes/toozle/toozle/_stock/assets/base.css
 * Archivo: base.css
 *
 * Estilos estructurales del sistema. Sin colores hardcodeados.
 * Todos los colores vienen de las variables definidas en colors.css.
 * Este archivo no debería necesitar override por cliente.
 */

:root {
  --radius:      16px;
  --radius-pill: 999px;
  --shadow:      0 18px 50px rgba(17, 17, 17, 0.08);
}

html {
  scroll-behavior: smooth;
}

body {
  font-family: 'Montserrat', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  color: var(--text);
  background: var(--white);
}

.section {
  padding: 88px 0;
  background: transparent;
}

.section-header {
  max-width: 760px;
  margin: 0 auto 48px;
  text-align: center;
}

.section-header h2 {
  margin: 10px 0 14px;
  font-size: clamp(2rem, 4vw, 2.5rem);
  line-height: 1.2;
  font-weight: 700;
}

/* Sesión 2026-06-06: cuando el header es el ÚNICO contenido del bloque
   (caso típico: CTA centrado), su margin-bottom de 48px se sumaba al
   padding inferior de la sección y el bloque quedaba asimétrico (más aire
   abajo que arriba). Si después del header vienen cards/form/mapa, el
   header no es :last-child y conserva su margen. */
.section > .container > .section-header:last-child {
  margin-bottom: 0;
}

.section-header p,
.lead-text,
.hero-lead {
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1.75;
}

.section-dark .section-header p,
.section-dark .lead-text,
.section-dark .hero-lead {
  color: rgba(255, 255, 255, 0.74);
}

.eyebrow,
.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
  padding: 6px 12px;
  border: 1px solid var(--primary-alpha-18);
  border-radius: var(--radius-pill);
  background: var(--primary-alpha-08);
  color: var(--primary);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* Sesión 2026-05-27 (§22.X): selector ampliado. Antes solo cubría
   .section-dark (legacy del hero/pages institucionales) y .is-dark (hex
   custom dark del Builder). Faltaban .section-bg-primary y .section-bg-dark
   que son las clases que emite tlp_blocks_resolve_section_classes() cuando
   el operador elige slug 'primary' o 'dark' del registry. Resultado del
   bug: eyebrow del header del bloque quedaba primary-tinted (mal contraste)
   en secciones con slug primary/dark, pero sí se veía blanco translúcido
   en secciones con hex custom oscuro — criterio inconsistente entre
   métodos de elegir el color. */
.section-dark .eyebrow,
.section-dark .hero-badge,
.is-dark .eyebrow,
.is-dark .hero-badge,
.section-bg-primary .eyebrow,
.section-bg-primary .hero-badge,
.section-bg-dark .eyebrow,
.section-bg-dark .hero-badge {
  border-color: rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.12);
  /* Literal #ffffff: dentro de .is-dark el token --white se redefine como
     rgba(255,255,255,.08) (superficies elevadas de cards). Si usaramos
     var(--white) aca el texto del badge quedaria casi transparente. */
  color: #ffffff;
}

/* === BADGE — VARIANTES EXPLÍCITAS (sesión 2026-05-01 B) ===================
   Cuando el operador elige un badge_style específico desde el panel,
   estas clases pisan el comportamiento "auto" (que hereda del contexto).
   Útil cuando el fondo del hero entra en conflicto con el primary del
   cliente y el badge se vuelve invisible o de bajo contraste.
   ========================================================================== */
.hero-badge.hero-badge-light {
  border-color: rgba(255, 255, 255, 0.32);
  background: rgba(255, 255, 255, 0.92);
  color: var(--text, #1a1a2e);
}
.hero-badge.hero-badge-dark {
  border-color: rgba(0, 0, 0, 0.18);
  background: rgba(0, 0, 0, 0.78);
  color: var(--white);
}
.hero-badge.hero-badge-primary {
  border-color: var(--primary);
  background: var(--primary);
  color: var(--white);
}

/* Sesión 2026-05-16: variantes alpha del hero-badge — paridad EXACTA con
   los eyebrows que renderean los bloques en contexto dark/primary
   (.section-dark .eyebrow, definido líneas 75-80) y con el eyebrow auto
   en contexto claro (línea 60-73). Mismos valores numéricos para que el
   chip del hero sea cromáticamente indistinguible del chip de los bloques.

   - white-alpha   : bg blanco translúcido (alpha .12) + texto blanco.
                     Mismo look que el eyebrow "Beneficios" / "Galería" del
                     screenshot del operador (bloques con section_color
                     primary o dark, fondo marrón intenso).
   - primary-alpha : bg primary translúcido (alpha-08) + texto primary +
                     border alpha-18. Mismo look que el eyebrow auto de un
                     bloque en contexto claro/soft. */
.hero-badge.hero-badge-white-alpha {
  border-color: rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.12);
  color: #ffffff;
}
.hero-badge.hero-badge-white-alpha i {
  color: #ffffff;
}
.hero-badge.hero-badge-primary-alpha {
  border-color: var(--primary-alpha-18, rgba(13, 110, 253, 0.18));
  background: var(--primary-alpha-08, rgba(13, 110, 253, 0.08));
  color: var(--primary);
}
.hero-badge.hero-badge-primary-alpha i {
  color: var(--primary);
}

/* === HERO BG — TIPOS NUEVOS (sesión 2026-05-01 B) =========================
   .hero-bg-auto    : sin override; respeta el background: var(--hero-gradient)
                      heredado de .hero (default histórico).
   .hero-bg-gradient: el helper del theme calcula el inline style con
                      linear-gradient(angle, color1, color2). La clase está
                      por si en el futuro se quiere matizar (overlay, etc.).
   .hero-bg-color   : el helper del theme calcula el inline style con
                      background plano.
   .hero-has-bg     : ya existía — para foto. Mantiene compatibilidad.
   ========================================================================== */
.hero-bg-auto,
.hero-bg-gradient,
.hero-bg-color {
  /* Sin reglas adicionales: el inline style del helper define el background.
     Estas clases existen como hooks por si se necesitan overrides desde
     colors.css del cliente. */
}

.hero {
  position: relative;
  overflow: hidden;
  padding: 112px 0;
  background: var(--hero-gradient);
  color: var(--white);
}

.hero-light {
  background: var(--light);
  color: var(--text);
}

/* ============================================================
   Hero Visual — refactor 2026-05-16
   ============================================================
   Modelo de tres modos para el wrapper de la imagen del hero,
   con sombra opcional independiente.

   Reemplaza al sistema previo `hero_image_framed` (bool):
     .hero-visual--none      = sin decoración (ex --bare)
     .hero-visual--outlined  = frame con padding interno
                               (comportamiento previo de framed:true)
     .hero-visual--flush     = frame con imagen al borde (overflow:hidden
                               recorta la imagen contra el border-radius)

   La sombra se aplica vía .hero-shadow-{none,soft,medium,strong},
   con vocabulario canon paridad con cards. El partial decide en qué
   elemento la aplica:
     - frame=='none'           → clase de sombra en el <img>
     - frame in {outlined,flush} → clase de sombra en el wrapper
   ============================================================ */

.hero-visual {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Modo NONE: sin decoración. Equivalente al `--bare` previo. */
.hero-visual.hero-visual--none {
  min-height: 0;
  border: none;
  border-radius: 0;
  background: transparent;
  backdrop-filter: none;
  padding: 0;
}

/* Modo OUTLINED: comportamiento previo de hero_image_framed:true. */
.hero-visual.hero-visual--outlined {
  min-height: 420px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 28px;
  background: rgba(255, 255, 255, 0.12);
  backdrop-filter: blur(12px);
  padding: 1.5rem;
}
.hero-light .hero-visual.hero-visual--outlined {
  border-color: var(--border);
  background: var(--white);
}
.hero-visual.hero-visual--outlined .hero-image {
  border-radius: 0.5rem;
}

/* Modo FLUSH: frame visible sin padding interno. La imagen llega a los
   cuatro bordes y se recorta contra el border-radius del wrapper.
   Sin min-height: la altura la define la imagen (height:auto + width:100%).
   Patrón emparentado con la galería flush §22.123. */
.hero-visual.hero-visual--flush {
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 28px;
  background: rgba(255, 255, 255, 0.12);
  backdrop-filter: blur(12px);
  padding: 0;
  overflow: hidden;
}
.hero-light .hero-visual.hero-visual--flush {
  border-color: var(--border);
  background: var(--white);
}
.hero-visual.hero-visual--flush .hero-image {
  width: 100%;
  max-width: 100%;
  border-radius: 0;
}

/* Sesión 2026-05-15 rev2: tamaño del bloque visual del hero.
   Sesión 2026-05-16: refactor — el modificador `--size-{sm,md,lg}` pasa
   del <img> al wrapper para que funcione en los tres modos (incluido
   flush, donde la imagen ocupa siempre el 100% del wrapper).
   Las clases `.hero-image--*` quedan deprecadas pero las dejamos
   declaradas como no-op por si quedó algún markup legacy. */
.hero-image {
  display: block;
  height: auto;
  max-width: 100%;
  margin-left: auto;
  margin-right: auto;
}

/* Tamaño aplicado al WRAPPER (canon nuevo). margin auto para centrar
   cuando max-width < 100%. Default lg = ocupa toda la columna. */
.hero-visual.hero-visual--size-sm { max-width: 50%; margin-left: auto; margin-right: auto; }
.hero-visual.hero-visual--size-md { max-width: 75%; margin-left: auto; margin-right: auto; }
.hero-visual.hero-visual--size-lg { max-width: 100%; }

/* Deprecadas — quedan declaradas como no-op para no romper landings
   pre-refactor que aún tengan estas clases en el markup cacheado. */
.hero-image--sm,
.hero-image--md,
.hero-image--lg { max-width: 100%; }

/* Sombras del hero (vocabulario canon paridad con tlp-card-shadow-*).
   Aplicables a `.hero-visual` (modos outlined/flush) o a `.hero-image`
   (modo none). El partial decide a quién agrega la clase. */
.hero-shadow-none   { box-shadow: none; }
.hero-shadow-soft   { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); }
.hero-shadow-medium { box-shadow: 0 14px 40px rgba(0, 0, 0, 0.14); }
.hero-shadow-strong { box-shadow: 0 24px 60px rgba(0, 0, 0, 0.22); }

/* ============================================================
   Overrides ortogonales — sesión 2026-05-16
   ============================================================
   Permiten apagar el bg o el border del wrapper sin tener que
   cambiar el modo Marco. Usan !important porque tienen que ganarle
   a las reglas específicas de los modos `--outlined` / `--flush`.

   - .hero-image-bg-none      → wrapper transparente + sin backdrop blur
                                (apaga también el efecto difuminado que
                                se ve detrás de PNGs transparentes)
   - .hero-image-border-none  → wrapper sin línea de borde

   El border-radius del wrapper se mantiene (lo controla el modo Marco).
   Para apagarlo, elegir Marco = "Sin marco (transparente)".
   ============================================================ */

.hero-visual.hero-image-bg-none {
  background: transparent !important;
  backdrop-filter: none !important;
}

.hero-visual.hero-image-border-none {
  border: none !important;
}

/* ============================================================
   Form Popup Modal — sesión 2026-05-16
   ============================================================
   Estilos canon para el modal del form popup que dispara cualquier
   botón con mode='form_popup' (§22.126). Replica el look del modal
   de contacto del home institucional (template-parts/home/modal-contacto.php
   + assets/css/toozle.css §1192-1250) — pero esos estilos viven en
   toozle.css que NO se carga en landings de cliente, por lo que los
   re-implementamos acá con scope `.tlp-form-popup-modal`.

   El shortcode [landing_plus_lead_form] adentro del modal ya rendea
   <h2 class="toozle-lead-form-title">{form_title} → no necesita header
   propio del modal. Los estilos abajo dan: card sin border + shadow
   grande + cerrar flotante + inputs pill con focus primary + button
   submit rounded-pill 100%.
   ============================================================ */

.tlp-form-popup-modal .modal-dialog {
  max-width: 540px;
}

.tlp-form-popup-modal .tlp-form-popup-card {
  border: 0;
  border-radius: 1.25rem;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
  overflow: hidden;
  position: relative;
}

/* Botón cerrar flotante, top-right del modal-content. */
.tlp-form-popup-modal .tlp-form-popup-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 2;
  opacity: 0.6;
}
.tlp-form-popup-modal .tlp-form-popup-close:hover {
  opacity: 1;
}

/* Header del shortcode: title + text más prolijos dentro del modal. */
.tlp-form-popup-modal .toozle-lead-form-title {
  font-weight: 700;
  margin-bottom: 0.5rem;
}
.tlp-form-popup-modal .toozle-lead-form-text {
  margin-bottom: 1.5rem;
}

/* Labels: peso semibold, tamaño chico. */
.tlp-form-popup-modal .toozle-lead-form-wrap .form-label {
  font-size: 0.875rem;
  font-weight: 600;
  margin-bottom: 0.4rem;
}

/* Inputs: pill suave con bg gris claro, focus primary. */
.tlp-form-popup-modal .toozle-lead-form-wrap .form-control {
  background: #f8f9fa;
  border: 1px solid #e9ecef;
  border-radius: 12px;
  padding: 0.75rem 1.1rem;
  font-size: 1rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.tlp-form-popup-modal .toozle-lead-form-wrap .form-control:focus {
  background: #fff;
  border-color: var(--primary);
  box-shadow: 0 0 0 0.2rem var(--primary-alpha-18, rgba(13, 110, 253, 0.18));
  outline: none;
}

/* Textarea: misma estética pero sin pill, con altura mínima. */
.tlp-form-popup-modal .toozle-lead-form-wrap textarea.form-control {
  border-radius: 12px;
  resize: vertical;
  min-height: 110px;
}

/* Botón submit: pill 100% width para ocupar todo el ancho. */
.tlp-form-popup-modal .toozle-lead-form-wrap .btn-primary {
  border-radius: 999px;
  padding: 0.9rem 1.5rem;
  font-weight: 600;
  width: 100%;
}

/* === HERO BRAND — línea de marca (sesión 2026-06-06) ======================
   Texto opcional entre el badge y el h1, para clientes sin logo que ponen
   su nombre/marca en texto (meta hero_brand_text, render condicional puro).
   Color: hereda del hero (blanco en bg oscuro vía .hero, var(--text) en
   .hero-light) — el operador lo pisa con el popover (inline style).
   Peso default 600; el editor lo pisa inline (hero_brand_weight).
   Tamaños: 3 presets curados que escalan con el viewport. Feedback del
   operador (2026-06-06): la escala original arrancaba muy abajo — el ex-XL
   pasó a ser el Chico y de ahí para arriba. El Grande queda debajo del h1
   del hero (clamp 2.6–4.7rem) para no competirle. */
.hero-brand {
  /* Sesión 2026-06-09: 18px arriba = mismo espaciado badge→contenido que
     usa el h1 del hero (su margin-top). Antes 0 dejaba la marca pegada al
     badge. */
  margin: 18px 0 6px;
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.hero-brand-size-s { font-size: clamp(1.6rem, 1.15rem + 2.2vw, 2.2rem); }
.hero-brand-size-m { font-size: clamp(2rem, 1.4rem + 3vw, 2.9rem); }
.hero-brand-size-l { font-size: clamp(2.4rem, 1.6rem + 4vw, 3.6rem); }

.hero h1 {
  margin: 18px 0;
  font-size: clamp(2.6rem, 6vw, 4.7rem);
  line-height: 1.05;
  font-weight: 800;
  letter-spacing: -0.04em;
}

.hero p {
  max-width: 640px;
}

.hero-actions,
.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 28px;
}

.btn {
  border-radius: var(--radius-pill);
  font-weight: 700;
}

.btn-wide {
  padding: 12px 34px;
}

.btn-accent {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--white);
}

.btn-accent:hover,
.btn-accent:focus {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--white);
}

.btn-whatsapp {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  /* sesión 2026-05-10: separamos color por botón. .btn-whatsapp consume la
     var del CTA; la sticky usa --whatsapp-floating. Default: verde stock.
     Las vars legacy --whatsapp / --whatsapp-hover siguen vivas en colors.css
     como aliases del flotante para retrocompat. */
  background: var(--whatsapp-cta);
  border-color: var(--whatsapp-cta);
  color: var(--white);
}

.btn-whatsapp:hover,
.btn-whatsapp:focus {
  background: var(--whatsapp-cta-hover);
  border-color: var(--whatsapp-cta-hover);
  color: var(--white);
}

.card {
  border-color: var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.card-clean {
  padding: 28px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--white);
  box-shadow: var(--shadow);
}

/* ── Sesión 2026-05-08 (cierre): modificadores per-card ──────────────────
   Selectores per-card que pisan el border / box-shadow base de .card-clean.
   Las tres opciones de borde y las tres de sombra son combinables. */

/* Borde */
.card-clean.tlp-card-border-none {
  border-color: transparent !important;
}
.card-clean.tlp-card-border-solid {
  /* default: usa var(--border). No hace falta override. */
}
.card-clean.tlp-card-border-dashed {
  border-style: dashed !important;
  border-color: rgba(0, 0, 0, 0.18) !important;
}
.is-dark .card-clean.tlp-card-border-dashed,
.section-bg-dark .card-clean.tlp-card-border-dashed,
.section-bg-primary.is-dark .card-clean.tlp-card-border-dashed {
  border-color: rgba(255, 255, 255, 0.22) !important;
}

/* Sombra */
.card-clean.tlp-card-shadow-none {
  box-shadow: none !important;
}
.card-clean.tlp-card-shadow-soft {
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08) !important;
}
/* Sesión 2026-05-16: medium y strong sumadas para paridad con el popover
   nuevo (none/soft/medium/strong/primary). Mismos valores que las clases
   .hero-shadow-* del hero — vocabulario consistente cross-componente. */
.card-clean.tlp-card-shadow-medium {
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.14) !important;
}
.card-clean.tlp-card-shadow-strong {
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.22) !important;
}
.card-clean.tlp-card-shadow-primary {
  box-shadow: 0 12px 30px var(--primary-shadow, rgba(13, 110, 253, 0.18)) !important;
}

.icon-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--primary-alpha-10);
  color: var(--primary);
  font-size: 1.35rem;
}

/* Variante grande — para cards centradas con ícono destacado */
.icon-circle-lg {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: var(--primary-alpha-10);
  color: var(--primary);
  font-size: 2rem;
}

.trust-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 26px;
}

.trust-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.08);
  color: inherit;
  font-size: 0.92rem;
}

.hero-light .trust-item,
.section-light .trust-item,
.section .trust-item {
  border-color: var(--border);
  background: var(--white);
}

.placeholder-visual {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 220px;
  border-radius: var(--radius);
  background: var(--placeholder-gradient);
  color: #94a3b8;
  text-align: center;
}

.placeholder-visual i {
  display: block;
  margin-bottom: 10px;
  font-size: 2.4rem;
  color: #94a3b8;
}

.form-shell {
  padding: 28px;
  border: 1px solid var(--border);
  border-radius: 22px;
  background: var(--white);
  box-shadow: var(--shadow);
}


/* INICIO FORMULARIO */
.form-card {
  padding: 28px;
  border: 1px solid var(--border);
  border-radius: 24px;
  background: var(--white);
  color: var(--text);
  box-shadow: 0 18px 30px rgba(17, 17, 17, 0.22);
}

.form-card .eyebrow {
  margin-bottom: 14px;
  color: var(--primary);
}

.form-card h2 {
  margin: 0 0 8px;
  color: var(--text);
  font-size: clamp(1.7rem, 3.4vw, 2.1rem);
  line-height: 1.1;
  font-weight: 800;
  letter-spacing: -0.04em;
}

.form-card p {
  margin-bottom: 18px;
  color: var(--muted);
  font-size: 0.98rem;
  line-height: 1.5;
}

.form-card form,
.form-card .gfh-form {
  margin-bottom: 0;
}

.form-card .row,
.form-card .gfh-row {
  display: block;
  margin: 0;
}

.form-card [class*="col-"] {
  width: 100%;
  max-width: 100%;
  flex: 0 0 100%;
  padding: 0;
  margin: 0 0 12px;
}

.form-card label {
  display: block;
  margin: 8px 0 6px;
  color: var(--text);
  font-size: 14px;
  font-weight: 700;
  line-height: 22px;
}

.form-card label:first-of-type {
  margin-top: 0;
}

.form-card input,
.form-card textarea,
.form-card select,
.form-card .form-control,
.form-card .form-select {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--input-border);
  border-radius: 12px;
  background: var(--white);
  color: var(--text);
  box-shadow: none;
  font-family: inherit;
  font-size: 15px;
  line-height: 22px;
}

.form-card input::placeholder,
.form-card textarea::placeholder,
.form-card select::placeholder {
  color: #adb5bd;
  opacity: 1;
}

.form-card textarea,
.form-card textarea.form-control {
  min-height: 96px;
  resize: vertical;
}

.form-card button,
.form-card input[type="submit"],
.form-card .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  margin: 14px 0 0;
  padding: 12px 22px;
  border: 0;
  border-radius: var(--radius-pill);
  background: linear-gradient(180deg, var(--primary), var(--primary-hover));
  color: var(--white);
  font-weight: 700;
  text-decoration: none;
}
/* CIERRA FORMULARIO */

/* INICIO LP-FORM-BLOCK
   Bloque builder de formulario. Replica los estilos de inputs/labels/botón
   del .form-card del hero, SIN la card chrome (sin bg/border/shadow/padding,
   el form vive dentro de la sección con su propio fondo) y SIN colapsar el
   .row (nombre+apellido siguen en una fila gracias al row g-3 del shortcode).
   El header del bloque (eyebrow/title/subtitle) lo rendea _block-header.php
   con el patrón canónico .section-header — el shortcode emite el form sin
   título/texto internos (show_title="0" show_text="0"). */

.lp-form-block {
  max-width: 720px;
  margin: 0 auto;
}

.lp-form-block .toozle-lead-form-wrap {
  background: transparent;
  border: 0;
  box-shadow: none;
  padding: 0;
}

.lp-form-block label,
.lp-form-block .form-label {
  display: block;
  margin: 8px 0 6px;
  color: var(--text);
  font-size: 14px;
  font-weight: 700;
  line-height: 22px;
}

.lp-form-block .form-control,
.lp-form-block input[type="text"],
.lp-form-block input[type="email"],
.lp-form-block input[type="tel"],
.lp-form-block input[type="url"],
.lp-form-block input[type="number"],
.lp-form-block textarea,
.lp-form-block select,
.lp-form-block .form-select {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--input-border);
  border-radius: 12px;
  background: var(--white);
  color: var(--text);
  box-shadow: none;
  font-family: inherit;
  font-size: 15px;
  line-height: 22px;
}

.lp-form-block .form-control::placeholder,
.lp-form-block input::placeholder,
.lp-form-block textarea::placeholder,
.lp-form-block select::placeholder {
  color: #adb5bd;
  opacity: 1;
}

.lp-form-block textarea,
.lp-form-block textarea.form-control {
  min-height: 96px;
  resize: vertical;
}

.lp-form-block .btn,
.lp-form-block button[type="submit"],
.lp-form-block input[type="submit"] {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  margin: 14px auto 0;
  padding: 12px 22px;
  border: 0;
  border-radius: var(--radius-pill);
  background: linear-gradient(180deg, var(--primary), var(--primary-hover));
  color: var(--white);
  font-weight: 700;
  text-decoration: none;
}
/* CIERRA LP-FORM-BLOCK */

.whatsapp-cta {
  padding: 36px;
  border: 1px solid var(--border);
  border-radius: 24px;
  background: var(--white);
  box-shadow: var(--shadow);
}

.whatsapp-cta-solid {
  background: var(--dark);
  color: var(--white);
}

.whatsapp-cta-outline {
  border-style: dashed;
  background: var(--light);
}

.calendar-frame {
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 22px;
  background: var(--white);
  box-shadow: var(--shadow);
}

.calendar-frame iframe {
  display: block;
  width: 100%;
  min-height: 720px;
  border: 0;
}

.footer-simple {
  padding: 28px 0;
}

/* Texto y separadores heredan color del contexto (.is-dark o no) */
.footer-simple .footer-sep {
  color: var(--muted);
}

/* Links del footer: color del texto por defecto, sin subrayado */
.footer-simple .footer-link {
  color: inherit;
}

.footer-simple .footer-link:hover {
  color: var(--primary);
  text-decoration: underline !important;
}

/* En contexto dark los links quedan blancos */
.footer-simple.is-dark .footer-link {
  color: rgba(255, 255, 255, 0.85);
}

.footer-simple.is-dark .footer-link:hover {
  color: #ffffff;
}

/* ── Back to top ──────────────────────────────────────────────────────────── */
/*  El botón se renderiza desde el orquestador (page-landing-plus.php)         */
/*  controlado por la meta back_to_top_enabled. Vive arriba del WhatsApp       */
/*  sticky cuando ambos están activos. El smooth scroll lo hace base.js.       */
/*  Tamaño igualado al WhatsApp sticky para consistencia visual.               */

.back-to-top {
  position: fixed;
  right: 30px;
  bottom: 30px;             /* posición baja por default (sin WhatsApp activo) */
  z-index: 50;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 60px;
  height: 60px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--primary);
  color: var(--white);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--shadow);
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 180ms ease, transform 180ms ease, background 180ms ease;
}

/* Sube cuando coexiste con WhatsApp sticky (apilados, WA abajo) */
.back-to-top.has-whatsapp {
  bottom: 110px;            /* arriba del WhatsApp (bottom 30 + 60 alto + 20 gap) */
}

.back-to-top:hover,
.back-to-top:focus {
  background: var(--primary-hover);
  color: var(--white);
  transform: translateY(0) scale(1.05);
  outline: none;
}

.back-to-top i {
  color: var(--white);
  line-height: 1;
}

.back-to-top.is-visible {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

@media (max-width: 768px) {
  .back-to-top {
    right: 20px;
    bottom: 20px;           /* mobile: posición baja por default */
    width: 50px;
    height: 50px;
    font-size: 1.25rem;
  }
  .back-to-top.has-whatsapp {
    bottom: 90px;           /* mobile arriba del WhatsApp (bottom 20 + 50 alto + 20 gap) */
  }
}

.reveal > * {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 520ms ease, transform 520ms ease;
}

.reveal.is-visible > * {
  opacity: 1;
  transform: translateY(0);
}

@media (max-width: 991.98px) {
  .section {
    padding: 64px 0;
  }

  .hero {
    padding: 80px 0;
  }
}

.contact-info-block {
  padding: 32px;
  border: 1px solid var(--border);
  border-radius: 18px;
  background: var(--white);
}

.contact-line strong,
.contact-line span {
  display: block;
}

.contact-line span {
  color: var(--muted);
}

.map-card {
  overflow: hidden;
  min-height: 420px;
  border: 1px solid var(--border);
  border-radius: 28px;
  background: var(--white);
  box-shadow: var(--shadow);
}

.landing-map {
  width: 100%;
  min-height: 420px;
}

.map-placeholder,
.video-placeholder {
  display: grid;
  min-height: 360px;
  place-items: center;
  align-content: center;
  gap: 10px;
  padding: 32px;
  border: 1px dashed var(--border);
  border-radius: 28px;
  background: var(--light);
  color: var(--muted);
  text-align: center;
}

.map-placeholder i,
.video-placeholder i {
  font-size: 48px;
  color: var(--primary);
}

.map-placeholder strong,
.video-placeholder strong {
  color: var(--text);
  font-size: 20px;
}

.coverage-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
}

.coverage-pill {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  padding: 10px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--white);
  color: var(--text);
  box-shadow: 0 8px 24px rgba(17, 17, 17, 0.05);
}

.coverage-pill i {
  color: var(--primary);
}

.step-card {
  position: relative;
  overflow: hidden;
  padding: 28px;
  border: 1px solid var(--border);
  border-radius: 24px;
  background: var(--white);
  box-shadow: var(--shadow);
}

/* Sesión 2026-05-12: la regla `.is-dark .step-card` que ponía fondo glass
   se eliminó. El fondo de la step-card ahora lo decide el contexto
   (sección + variante), ver bloque "Sistema de contexto cromático per-card". */

.step-number {
  position: absolute;
  top: 18px;
  right: 22px;
  color: var(--primary-alpha-12);
  font-size: 42px;
  font-weight: 800;
  line-height: 1;
}

.stats-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 28px;
  background: var(--white);
  box-shadow: var(--shadow);
}

.stat-item {
  display: grid;
  gap: 6px;
  padding: 28px;
  text-align: center;
}

.stat-item + .stat-item {
  border-left: 1px solid var(--border);
}

.stat-item strong {
  color: var(--primary);
  font-size: clamp(32px, 5vw, 52px);
  line-height: 1;
}

.stat-item span {
  color: var(--muted);
}

.logos-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}

.logo-item {
  display: grid;
  min-height: 96px;
  place-items: center;
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: 20px;
  background: var(--white);
  color: var(--muted);
  font-weight: 700;
  text-align: center;
}

.logo-item img {
  max-width: 150px;
  max-height: 54px;
  object-fit: contain;
}

.video-card {
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 28px;
  background: var(--white);
  box-shadow: var(--shadow);
}

.video-card iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

.download-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
  padding: 32px;
  border: 1px solid var(--border);
  border-radius: 28px;
  background: var(--white);
  box-shadow: var(--shadow);
}

.download-card h2 {
  margin-bottom: 12px;
}

.download-file {
  display: grid;
  min-width: 240px;
  gap: 12px;
  justify-items: center;
  padding: 24px;
  border: 1px dashed var(--border);
  border-radius: 22px;
  background: var(--light);
  text-align: center;
}

.download-file i {
  color: var(--primary);
  font-size: 44px;
}

.pricing-card {
  padding: 30px;
  border: 1px solid var(--border);
  border-radius: 28px;
  background: var(--white);
  box-shadow: var(--shadow);
}

.pricing-card.is-featured {
  border-color: var(--primary-alpha-38);
  box-shadow: 0 24px 70px var(--primary-shadow);
}

.pricing-price {
  margin: 18px 0;
  color: var(--primary);
  font-size: clamp(34px, 5vw, 52px);
  font-weight: 800;
  line-height: 1;
}

.pricing-list {
  display: grid;
  gap: 10px;
  padding: 0;
  margin: 22px 0 0;
  list-style: none;
}

.pricing-list li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  color: var(--muted);
}

.pricing-list i {
  color: var(--primary);
}

.guarantee-strip {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.guarantee-item {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 22px;
  border: 1px solid var(--border);
  border-radius: 22px;
  background: var(--white);
}

.guarantee-item > i {
  color: var(--primary);
  font-size: 28px;
}

.guarantee-item strong,
.guarantee-item span {
  display: block;
}

.guarantee-item span {
  color: var(--muted);
  font-size: 14px;
}

@media (max-width: 991.98px) {
  .stats-strip,
  .logos-strip,
  .guarantee-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .stat-item + .stat-item {
    border-left: 0;
    border-top: 1px solid var(--border);
  }

  .download-card {
    align-items: stretch;
    flex-direction: column;
  }

  .download-file {
    min-width: 0;
  }
}

@media (max-width: 575.98px) {
  .stats-strip,
  .logos-strip,
  .guarantee-strip {
    grid-template-columns: 1fr;
  }

  .map-card,
  .landing-map {
    min-height: 340px;
  }
}
/* INICIO PARTIALS PROFESSIONALS */
.professional-profile {
  padding: 80px 0;
}

.professional-profile-card {
  padding: 32px;
  border: 1px solid var(--border);
  border-radius: 28px;
  background: var(--white);
  box-shadow: 0 18px 50px rgba(17, 17, 17, 0.06);
}

.is-dark .professional-profile-card {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.12);
  box-shadow: none;
}

/* Sesión 2026-06-09: toggle "Mostrar contenedor" del bloque Imagen + texto.
   Sin contenedor (card_enabled=false): el contenido ocupa el ancho pleno,
   sin marco, padding ni fondo — paridad con un bloque de cards que llega al
   máximo. Mantiene la clase .professional-profile-card para que las reglas
   de .professional-bio y el contexto cromático sigan aplicando. */
.professional-profile-card.professional-profile-card--bare {
  padding: 0;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
}
.is-dark .professional-profile-card.professional-profile-card--bare {
  background: transparent;
  border: 0;
}

/* Sesión 2026-06-06 rev3: marco con espaciado interno para la imagen del
   bloque Imagen + texto (toggle "Espaciado de la imagen"). El fondo lo da
   photo_bg (inline); el padding deja respirar la imagen adentro del marco.
   En modo cuadrado (photo_rounded off) la imagen interna también va recta. */
.professional-photo.professional-photo-padded {
  padding: 14px;
}
.professional-photo.professional-photo-padded img {
  border-radius: 14px;
}
.professional-photo.professional-photo-square,
.professional-photo.professional-photo-square img {
  border-radius: 0;
}

/* Sesión 2026-06-06: bio del bloque Imagen + texto. El rol/subtítulo es
   muted (regla del wrapper inline); la bio va en color de texto pleno y
   con cuerpo propio para que se distinga — antes ambos eran <p> idénticos
   y la bio "no se veía". */
.professional-profile-card .professional-bio {
  color: var(--text);
  font-size: 1.05rem;
  line-height: 1.7;
}

/* Sesión 2026-06-06: contraste en cards primary/dark — las variantes
   tlp-card-primary/dark redefinen --text/--muted; con color: var(--text)
   en la card, todo el texto heredado (h2, bio) resuelve al blanco. */
.professional-profile-card.tlp-card-context-dark {
  color: var(--text);
}
.professional-profile-card.tlp-card-context-dark h2 {
  color: var(--text);
}
.professional-profile-card.tlp-card-context-dark .tlp-block-header-inline p {
  color: var(--muted);
}

.professional-profile-compact {
  max-width: 460px;
  margin: 0 auto;
}

.professional-profile-highlight {
  color: var(--white);
  background: linear-gradient(135deg, var(--primary), var(--accent));
}

.professional-profile-highlight .text-secondary,
.professional-profile-highlight p {
  color: rgba(255, 255, 255, 0.82) !important;
}

.professional-photo {
  overflow: hidden;
  width: 100%;
  border-radius: 26px;
  background: var(--photo-placeholder-gradient);
  aspect-ratio: 4 / 5;
}

/* Sesión 2026-06-09: layout vertical (apilado) del bloque Imagen + texto.
   Las zonas (título, subtítulo, foto, texto) se apilan en el orden que
   elige el operador. La foto va con su max-width inline (por photo_size) y
   se centra con .mx-auto cuando el header está centrado. Ritmo vertical
   propio para que no quede pegada al texto de arriba/abajo. */
.professional-vertical .professional-photo-vertical {
  margin-top: 1.5rem;
  margin-bottom: 1.5rem;
}

/* Sesión 2026-05-15: tamaños alternativos de la foto. El ancho de columna
   lo decide el partial (col-lg-3/5/6). Acá solo cambiamos el aspect-ratio
   por modificador. 'md' usa el default (4/5) — sin clase modificadora. */
.professional-photo-sm {
  aspect-ratio: 1 / 1;
}

.professional-photo-lg {
  aspect-ratio: 3 / 4;
}

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

.professional-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.professional-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  color: var(--muted);
  font-size: 14px;
  font-weight: 700;
  background: var(--white);
}

.professional-profile-highlight .professional-meta-item {
  border-color: rgba(255, 255, 255, 0.25);
  color: var(--white);
  background: rgba(255, 255, 255, 0.12);
}

@media (max-width: 991.98px) {
  .professional-profile {
    padding: 56px 0;
  }

  .professional-photo,
  .professional-photo img {
    max-height: 520px;
  }
}
/* CIERRA PARTIALS PROFESSIONALS */

/* ── Fondos de hero dinámicos ─────────────────────────────────────────────── */

/* hero-bg-color: el color viene como style inline desde layout.php */
.hero-bg-color {
  color: var(--white);
}

/* hero-has-bg: imagen de fondo assets/img/hero-bg.jpg */
.hero-has-bg {
  background-color: var(--hero-gradient-dark);
  background-size: cover;
  background-position: center;
  color: var(--white);
}

/* NOTA (sesión 2026-05-02 parte 7): el overlay automático via ::before fue
   removido. Antes existía un overlay rgba(0,0,0,0.52) que se aplicaba SIEMPRE
   sobre cualquier foto, incluso en modo `photo` puro y en `photo-gradient`
   con alpha 100%. Hoy:
     - `photo` puro: foto sin overlay automático. Si una landing necesita
       legibilidad, usa los campos legacy `hero_overlay_*` que el helper PHP
       arma como capa CSS inline (tlp_build_overlay_layer).
     - `photo-gradient`: el gradiente del operador define el overlay y respeta
       sus alphas. Sin capa adicional.
   El `colors.css` de un cliente puede agregar su propio overlay decorativo
   si lo necesita, pero NO se aplica por default desde el stock. */

/* el contenido queda por encima de eventual overlay (z-index defensivo) */
.hero-has-bg > .container {
  position: relative;
  z-index: 1;
}

/* ── Clases auxiliares de texto y card — independientes de Bootstrap ─────── */
/* Usan variables del sistema para adaptarse a cualquier contexto de color.   */

.tlp-muted {
  color: var(--muted);
}

.tlp-muted-inverse {
  color: rgba(255, 255, 255, 0.75);
}

.tlp-badge-soft {
  display: inline-block;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: var(--light);
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 700;
}

/* ── Variantes de card (Sesión 2026-05-12: rewrite) ────────────────────────
   Las cuatro variantes definen fondo sólido SIEMPRE, sin depender del
   contexto exterior. El color del contenido lo decide tlp-card-context-*
   que _card-universal / _card-pricing / _card-testimonial emiten junto
   con estas. */

.tlp-card-white {
  background: #ffffff !important;
  border-color: rgba(0, 0, 0, 0.10) !important;
}

.tlp-card-soft {
  background: #f5f5f5 !important;
  border-color: rgba(0, 0, 0, 0.08) !important;
}

.tlp-card-primary {
  background: var(--primary) !important;
  border-color: transparent !important;
}

.tlp-card-dark {
  background: var(--dark) !important;
  border-color: rgba(255, 255, 255, 0.12) !important;
}

/* Card primary sobre fondo primary: borde y sombra default para recortarse,
   porque card y sección comparten color. Los modificadores per-card
   (tlp-card-border-* / tlp-card-shadow-*) del editor pisan estos defaults. */
.section-bg-primary .card-clean.tlp-card-primary,
.section-bg-primary .step-card.tlp-card-primary,
.section-bg-primary .pricing-card.tlp-card-primary {
  border: 1px solid rgba(255, 255, 255, 0.22) !important;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.18) !important;
}

.section-bg-primary .card-clean.tlp-card-primary.tlp-card-border-none,
.section-bg-primary .step-card.tlp-card-primary.tlp-card-border-none,
.section-bg-primary .pricing-card.tlp-card-primary.tlp-card-border-none {
  border-color: transparent !important;
}
.section-bg-primary .card-clean.tlp-card-primary.tlp-card-shadow-none,
.section-bg-primary .step-card.tlp-card-primary.tlp-card-shadow-none,
.section-bg-primary .pricing-card.tlp-card-primary.tlp-card-shadow-none {
  box-shadow: none !important;
}

/* icon-circle invertido para usar sobre fondo primario */
.tlp-icon-circle-inverse {
  background: rgba(255, 255, 255, 0.20);
  color: #ffffff;
}

/* ── Logo del cliente ─────────────────────────────────────────────────────── */
/*                                                                             */
/*  Contenedor de altura fija, ancho libre. El logo se adapta solo            */
/*  sin distorsionarse sea cual sea su proporción (horizontal, vertical, 1:1) */
/*                                                                             */
/*  Uso: assets/img/logo.png en la carpeta del cliente.                       */
/*  Si no existe el archivo, el slot no se renderiza.                         */

.hero-logo {
  display: block;
  margin-bottom: 20px;
}

.hero-logo img {
  display: block;
  height: 48px;
  width: auto;
  /* Tope en px en desktop, pero nunca más ancho que el contenedor: en
     resoluciones chicas el logo se achica (object-fit:contain mantiene el
     ratio) en vez de tocar/pasar los bordes del hero. */
  max-width: min(240px, 100%);
  object-fit: contain;
  object-position: left center;
}

/* En heroes centrados el logo se centra también */
.hero-logo.hero-logo-center {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.hero-logo.hero-logo-center img {
  margin: 0 auto;
  object-position: center;
}

/* Alineación explícita del logo desde el panel (hero_logo_align).          */
/* El img es display:block, así que margin auto lo empuja al lado opuesto.  */
.hero-logo.hero-logo-left img {
  margin-left: 0;
  margin-right: auto;
  object-position: left center;
}

.hero-logo.hero-logo-right img {
  margin-left: auto;
  margin-right: 0;
  object-position: right center;
}

/* Logo en profile — más pequeño, antes del eyebrow */
.profile-logo {
  display: block;
  margin-bottom: 16px;
}

.profile-logo img {
  display: block;
  height: 36px;
  width: auto;
  max-width: 180px;
  object-fit: contain;
  object-position: left center;
}

/* En contexto dark el logo puede necesitar filtro para ser visible */
.is-dark .hero-logo img,
.is-dark .profile-logo img {
  filter: brightness(0) invert(1);
}


/*                                                                             */
/*  Aplicadas por layout.php en el wrapper de cada bloque según               */
/*  el campo "bg" del objeto en active_blocks.                                 */
/*                                                                             */
/*  .section-bg-white   → fondo blanco (default)                              */
/*  .section-bg-soft    → fondo gris suave (--light)                          */
/*  .section-bg-primary → fondo color primario del cliente                    */
/*  .section-bg-dark    → fondo oscuro                                        */

.section-bg-white {
  background: var(--white);
}

.section-bg-soft {
  background: var(--light);
}

.section-bg-primary {
  background: var(--primary);
}

.section-bg-dark {
  background: var(--dark);
}

/* ── Contexto de sección: scheme (color de texto y elementos) ────────────── */
/*                                                                             */
/*  .is-dark redefine las variables de color dentro del bloque.               */
/*  Los partials no se modifican — leen var(--text), var(--muted), etc.       */
/*  y el contexto los colorea automáticamente.                                 */

.is-dark {
  --text:               #ffffff;
  --muted:              rgba(255, 255, 255, 0.70);
  --border:             rgba(255, 255, 255, 0.15);
  --input-border:       rgba(255, 255, 255, 0.25);
  --shadow:             0 18px 50px rgba(0, 0, 0, 0.24);

  /* Cards y superficies elevadas dentro de un contexto dark */
  --white:              rgba(255, 255, 255, 0.08);
  --light:              rgba(255, 255, 255, 0.05);

  color: #ffffff;
}

/* Elementos puntuales que necesitan ajuste explícito en contexto dark */

.is-dark .section-header p,
.is-dark .lead-text,
.is-dark .hero-lead {
  color: rgba(255, 255, 255, 0.74);
}

/* ═══════════════════════════════════════════════════════════════════════════
 * SESIÓN 2026-05-12 — Sistema de contexto cromático per-card
 *
 * Las cards reciben tlp-card-context-{light|dark} desde _card-universal /
 * _card-pricing / _card-testimonial. Esa clase define el sub-contexto
 * cromático: todo el contenido interno (h*, p, muted, placeholder,
 * icon-circle, trust-list, pricing-list, badge, botón, trust-item, etc.)
 * lee del contexto de la card, no del de la sección.
 *
 * Beneficio: una card white dentro de sección primary tiene contenido
 * legible (texto oscuro) aunque el contexto exterior sea is-dark.
 * ═══════════════════════════════════════════════════════════════════════════ */

/* Contexto LIGHT — esquema cromático claro. Activa cuando la card tiene
   superficie clara (variante white/soft o inherit en sección clara). */
.tlp-card-context-light,
.tlp-card-white,
.tlp-card-soft {
  --text:               #212529;
  --muted:              #6c757d;
  --border:             rgba(0, 0, 0, 0.10);
  --white:              #ffffff;
  --light:              #f5f5f5;
  color:                var(--text);
}

/* Contexto DARK — esquema cromático oscuro. Activa cuando la card tiene
   superficie oscura (variante primary/dark o inherit en sección oscura). */
.tlp-card-context-dark,
.tlp-card-primary,
.tlp-card-dark {
  --text:               #ffffff;
  --muted:              rgba(255, 255, 255, 0.70);
  --border:             rgba(255, 255, 255, 0.15);
  color:                #ffffff;
}

/* Cards inherit en sección oscura: fondo sólido del color de sección. */
.section-bg-primary .tlp-card-context-dark.card-clean,
.section-bg-primary .tlp-card-context-dark.step-card {
  background: var(--primary);
  border-color: rgba(255, 255, 255, 0.22);
}
.section-bg-dark .tlp-card-context-dark.card-clean,
.section-bg-dark .tlp-card-context-dark.step-card {
  background: var(--dark);
  border-color: rgba(255, 255, 255, 0.15);
}

/* whatsapp-cta y form-shell: viven fuera del sistema de cards, conservan
   tratamiento glass histórico en sección dark. */
.is-dark .whatsapp-cta,
.is-dark .form-shell {
  border-color: rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.06);
}

.is-dark .professional-meta-item,
.is-dark .trust-item,
.is-dark .coverage-pill {
  border-color: rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.08);
  color: #ffffff;
}

/* Cuando esos elementos viven dentro de una card de contexto light,
   se resetean al esquema claro. */
.tlp-card-context-light .professional-meta-item,
.tlp-card-context-light .trust-item,
.tlp-card-context-light .coverage-pill {
  border-color: rgba(0, 0, 0, 0.10);
  background: transparent;
  color: var(--text);
}

.is-dark .logo-item {
  border-color: rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.70);
}

.is-dark .guarantee-item {
  border-color: rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.06);
}

.is-dark .guarantee-item span {
  color: rgba(255, 255, 255, 0.65);
}

/* pricing-list dentro de cards lee del contexto, no de sección. */
.tlp-card-context-dark .pricing-list li {
  color: rgba(255, 255, 255, 0.74);
}

.tlp-card-context-dark .pricing-list i {
  color: #ffffff;
}

.tlp-card-context-light .pricing-list li {
  color: var(--muted);
}

.tlp-card-context-light .pricing-list i {
  color: var(--primary);
}

.is-dark .stat-item span {
  color: rgba(255, 255, 255, 0.65);
}

.is-dark .stat-item + .stat-item {
  border-left-color: rgba(255, 255, 255, 0.12);
}

.is-dark .stats-strip,
.is-dark .logos-strip .logo-item,
.is-dark .guarantee-strip .guarantee-item {
  border-color: rgba(255, 255, 255, 0.12);
}

/* Sesión 2026-05-15: en bg primary el número (.stat-item strong) quedaba
   var(--primary) sobre el mismo color del wrapper → invisible. Lo forzamos
   a blanco para contraste. Cubre tanto bg-primary con .is-dark como sin él
   (primary claro o saturado). En bg-dark el primary brillante sobre fondo
   negro contrasta bien, así que ese caso se mantiene como está. */
.section-bg-primary .stat-item strong {
  color: #ffffff;
}

/* Inputs en contexto dark */
.is-dark input,
.is-dark textarea,
.is-dark select,
.is-dark .form-control,
.is-dark .form-select {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.20);
  color: #ffffff;
}

.is-dark input::placeholder,
.is-dark textarea::placeholder {
  color: rgba(255, 255, 255, 0.45);
}

/* Acordeón en contexto dark */
.is-dark .accordion-item {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.12);
}

.is-dark .accordion-button {
  background: rgba(255, 255, 255, 0.04);
  color: #ffffff;
}

.is-dark .accordion-button:not(.collapsed) {
  background: rgba(255, 255, 255, 0.10);
  color: #ffffff;
}

.is-dark .accordion-button::after {
  filter: invert(1);
}

/* ── Combinaciones predefinidas frecuentes ───────────────────────────────── */
/*  section-bg-primary + is-dark: texto claro sobre color primario            */
/*  section-bg-dark    + is-dark: texto claro sobre oscuro                    */
/*  section-bg-soft    (sin is-dark): gris suave con texto normal             */
/*  section-bg-white   (sin is-dark): blanco con texto normal (default)       */

/* ── Botones en contexto dark ────────────────────────────────────────────── */
/* btn-outline-primary desaparece sobre fondo primario — se convierte a light */
.is-dark .btn-outline-primary {
  border-color: rgba(255, 255, 255, 0.70) !important;
  color: #ffffff !important;
}

.is-dark .btn-outline-primary:hover,
.is-dark .btn-outline-primary:focus {
  background: rgba(255, 255, 255, 0.15) !important;
  border-color: #ffffff !important;
  color: #ffffff !important;
}

/* btn-primary sobre fondo primario — fondo blanco translúcido para diferenciarlo */
.is-dark .btn-primary {
  background: rgba(255, 255, 255, 0.22) !important;
  border-color: rgba(255, 255, 255, 0.40) !important;
  color: #ffffff !important;
}

.is-dark .btn-primary:hover,
.is-dark .btn-primary:focus {
  background: rgba(255, 255, 255, 0.32) !important;
  border-color: rgba(255, 255, 255, 0.60) !important;
  color: #ffffff !important;
}

/* ──────────────────────────────────────────────────────────────────────────
   BOTONES DE CARDS DEL BUILDER — 8 variantes canónicas
   ──────────────────────────────────────────────────────────────────────────
   Sesión 2026-05-13: las cards del Builder tienen 4 presentaciones de fondo
   (white / soft / primary / dark). Cada una mapea por default a una variante
   de botón sólida con buen contraste; el operador puede pisar el default
   con cualquiera de las 8 variantes vía item.style.button_variant.

   Todas las variantes:
     - Llevan .btn (Bootstrap) + .tlp-btn (padding propio del builder).
     - Anulan el padding base del btn de Bootstrap.
   ────────────────────────────────────────────────────────────────────────── */

/* Sesión 2026-05-13 rev3: padding cómodo + pill completo. Aplica a las 8
   variantes de botón de cards del builder. */
.tlp-btn {
  padding: 0.625rem 1.125rem;
  font-weight: 600;
  border-radius: 999px;
  line-height: 1.3;
  transition: background-color .15s ease, color .15s ease,
              border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}

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

/* === Sólidas ============================================================ */

.tlp-btn-solid-primary {
  background: var(--primary);
  border: 1px solid var(--primary);
  color: #ffffff;
}
.tlp-btn-solid-primary:hover,
.tlp-btn-solid-primary:focus {
  background: var(--primary);
  border-color: var(--primary);
  color: #ffffff;
  filter: brightness(0.92);
}

.tlp-btn-solid-dark {
  background: var(--dark, #212529);
  border: 1px solid var(--dark, #212529);
  color: #ffffff;
}
.tlp-btn-solid-dark:hover,
.tlp-btn-solid-dark:focus {
  background: var(--dark, #212529);
  border-color: var(--dark, #212529);
  color: #ffffff;
  filter: brightness(1.15);
}

.tlp-btn-solid-white-primary {
  background: #ffffff;
  border: 1px solid #ffffff;
  color: var(--primary);
}
.tlp-btn-solid-white-primary:hover,
.tlp-btn-solid-white-primary:focus {
  background: #ffffff;
  border-color: #ffffff;
  color: var(--primary);
  filter: brightness(0.95);
}

.tlp-btn-solid-white-dark {
  background: #ffffff;
  border: 1px solid #ffffff;
  color: var(--dark, #212529);
}
.tlp-btn-solid-white-dark:hover,
.tlp-btn-solid-white-dark:focus {
  background: #ffffff;
  border-color: #ffffff;
  color: var(--dark, #212529);
  filter: brightness(0.95);
}

/* === Outline (border + texto mismo color, bg transparente) ============== */

.tlp-btn-outline-primary {
  background: transparent;
  border: 1px solid var(--primary);
  color: var(--primary);
}
.tlp-btn-outline-primary:hover,
.tlp-btn-outline-primary:focus {
  background: var(--primary-alpha-08, rgba(13, 110, 253, 0.08));
  border-color: var(--primary);
  color: var(--primary);
}

.tlp-btn-outline-dark {
  background: transparent;
  border: 1px solid var(--dark, #212529);
  color: var(--dark, #212529);
}
.tlp-btn-outline-dark:hover,
.tlp-btn-outline-dark:focus {
  background: rgba(0, 0, 0, 0.06);
  border-color: var(--dark, #212529);
  color: var(--dark, #212529);
}

.tlp-btn-outline-white {
  background: transparent;
  border: 1px solid #ffffff;
  color: #ffffff;
}
.tlp-btn-outline-white:hover,
.tlp-btn-outline-white:focus {
  background: rgba(255, 255, 255, 0.12);
  border-color: #ffffff;
  color: #ffffff;
}

.tlp-btn-outline-soft {
  background: transparent;
  border: 1px solid rgba(0, 0, 0, 0.20);
  color: var(--muted, #6c757d);
}
.tlp-btn-outline-soft:hover,
.tlp-btn-outline-soft:focus {
  background: rgba(0, 0, 0, 0.04);
  border-color: rgba(0, 0, 0, 0.30);
  color: var(--text, #212529);
}

/* En contexto cromático dark, el outline-soft cambia a paleta blanca para
   conservar contraste cuando se usa en card primary/dark. */
.tlp-card-context-dark .tlp-btn-outline-soft {
  border-color: rgba(255, 255, 255, 0.30);
  color: rgba(255, 255, 255, 0.80);
}
.tlp-card-context-dark .tlp-btn-outline-soft:hover,
.tlp-card-context-dark .tlp-btn-outline-soft:focus {
  background: rgba(255, 255, 255, 0.10);
  border-color: rgba(255, 255, 255, 0.50);
  color: #ffffff;
}

/* ── icon-circle según contexto de la card ──────────────────────────────────
   Sesión 2026-05-12: la apariencia del icon-circle la decide el contexto
   cromático de la card, no la sección. Una card white dentro de sección
   primary tiene el icon-circle con tinte primary; una card primary en
   cualquier sección lo tiene blanco translúcido. */
.tlp-card-context-dark .icon-circle,
.tlp-card-context-dark .icon-circle-lg {
  background: rgba(255, 255, 255, 0.20);
  color: #ffffff;
}

.tlp-card-context-light .icon-circle,
.tlp-card-context-light .icon-circle-lg {
  background: var(--primary-alpha-12);
  color: var(--primary);
}

/* tlp-icon-circle-inverse dentro de tlp-card-primary siempre mantiene su estilo,
   independientemente del contexto de sección */
.tlp-card-primary .tlp-icon-circle-inverse {
  background: rgba(255, 255, 255, 0.20) !important;
  color: #ffffff !important;
}

/* ── code en contexto dark ───────────────────────────────────────────────── */
/* Bootstrap colorea code en rojo — lo neutralizamos */
.is-dark code {
  background: rgba(255, 255, 255, 0.15);
  color: rgba(255, 255, 255, 0.90);
  padding: 2px 6px;
  border-radius: 4px;
}

/* ── btn-whatsapp en contexto dark ───────────────────────────────────────── */
/* El texto verde del ícono/label no hereda bien — forzamos blanco */
.is-dark .btn-whatsapp {
  color: #ffffff !important;
}

.is-dark .btn-whatsapp:hover,
.is-dark .btn-whatsapp:focus {
  color: #ffffff !important;
}

/* ── CTA sólido en contexto dark ─────────────────────────────────────────── */
/* whatsapp-cta-solid tiene fondo --dark que sobre primario/dark se pierde   */
.is-dark .whatsapp-cta-solid {
  background: rgba(0, 0, 0, 0.35);
  border-color: rgba(255, 255, 255, 0.10);
}

/* El h3 dentro de cta-solid toma color oscuro — forzamos blanco */
.is-dark .whatsapp-cta-solid h1,
.is-dark .whatsapp-cta-solid h2,
.is-dark .whatsapp-cta-solid h3,
.is-dark .whatsapp-cta-solid h4 {
  color: #ffffff;
}

/* ── tlp-badge-soft en contexto dark ────────────────────────────────────── */
/*  Sesión 2026-05-14: color a blanco puro (antes rgba 0.85). Bajo contraste */
/*  detectado en auditoría de los 28 bloques sobre fondo primary/dark.       */
.is-dark .tlp-badge-soft {
  background: rgba(255, 255, 255, 0.15);
  color: #ffffff;
}

/* ── Sesión 2026-06-12: badge en card de contexto claro dentro de sección
   oscura/primary ───────────────────────────────────────────────────────────
   La regla de arriba (.is-dark .tlp-badge-soft) vuelve el badge blanco para
   que se lea sobre el fondo oscuro de la sección. Pero una card clara
   (blanca/gris) adentro de esa sección emite tlp-card-context-light: ahí el
   badge tiene que mantener su look claro (fondo var(--light), texto muted),
   si no queda blanco→invisible. Mismo criterio que §22.272 (la card pisa el
   contexto de la sección). Specificity (0,3,0) > (0,2,0) de la regla previa. */
.is-dark .tlp-card-context-light .tlp-badge-soft {
  background: var(--light);
  color: var(--muted);
}

/* ── Textos dentro de cards con fondo propio en contexto is-dark ────────── */
/*                                                                            */
/*  .card-clean, .step-card y similares tienen background propio             */
/*  (rgba blanco translúcido en is-dark). Eso los "saca" del flujo de        */
/*  herencia de color del wrapper, y los h* y p quedan sin color definido,   */
/*  tomando el del body (#212529) en lugar del blanco del contexto.          */
/*                                                                            */
/*  Solución: forzar color explícito en los elementos de texto dentro        */
/*  de cada superficie elevada que aparece en is-dark.                        */
/*                                                                            */
/*  Excepción: tlp-card-primary y tlp-card-soft tienen fondo propio          */
/*  independiente del contexto y ya definen su propio color — no se tocan.   */

/* Sesión 2026-05-12: el color del contenido (h*, p, muted) dentro de una
   card lo decide el contexto cromático de la card, no el de la sección.
   Esto permite que tlp-card-white dentro de .is-dark tenga texto oscuro,
   y que tlp-card-primary fuera de .is-dark tenga texto blanco. */

.tlp-card-context-light h1,
.tlp-card-context-light h2,
.tlp-card-context-light h3,
.tlp-card-context-light h4,
.tlp-card-context-light h5,
.tlp-card-context-light h6 {
  color: var(--text);
}

.tlp-card-context-light p,
.tlp-card-context-light .tlp-muted {
  color: var(--muted);
}

.tlp-card-context-dark h1,
.tlp-card-context-dark h2,
.tlp-card-context-dark h3,
.tlp-card-context-dark h4,
.tlp-card-context-dark h5,
.tlp-card-context-dark h6 {
  color: #ffffff;
}

.tlp-card-context-dark p,
.tlp-card-context-dark .tlp-muted {
  color: rgba(255, 255, 255, 0.74);
}

/* step-number según contexto de la step-card. */
.tlp-card-context-dark .step-number {
  color: rgba(255, 255, 255, 0.18);
}
.tlp-card-context-light .step-number {
  color: var(--primary-alpha-12);
}

/* ── eyebrow en contexto is-dark ─────────────────────────────────────────── */
/*  Por defecto usa color: var(--primary) que sobre fondo oscuro desaparece  */
/*  si el primario del cliente es un color oscuro (ej: IPA verde oscuro).    */

/* Sesión 2026-05-27: la regla .is-dark .eyebrow vivía acá duplicando
   el tratamiento dark del eyebrow. Se consolidó en el bloque principal
   (líneas 75-92) que ahora cubre .section-dark, .is-dark, .section-bg-primary
   y .section-bg-dark con los mismos valores. Eliminada de acá para evitar
   dos fuentes de verdad. */

/* ── section-header h2 en contexto is-dark ──────────────────────────────── */
/*  h2 no tiene color explícito — hereda del wrapper. En algunos contextos   */
/*  Bootstrap puede pisar esa herencia. Forzamos blanco para garantizar.     */

.is-dark .section-header h2,
.is-dark .section-header h3 {
  color: #ffffff;
}

/* ── btn-light dentro de tlp-card-primary ───────────────────────────────── */
/*  tlp-card-primary fuerza color: #ffffff !important en todo su contenido.  */
/*  btn-light tiene texto oscuro por diseño pero la herencia lo pisa.        */

.tlp-card-primary .btn-light {
  color: var(--dark) !important;
}

/* ── trust-item dentro de tlp-card-primary ──────────────────────────────── */
/*  trust-item tiene color: inherit — sobre fondo primario necesita blanco    */

.tlp-card-primary .trust-item {
  border-color: rgba(255, 255, 255, 0.30);
  background: rgba(255, 255, 255, 0.15);
  color: #ffffff;
}

/* =========================================
 * 17. WHATSAPP STICKY BUTTON
 * Botón flotante de WhatsApp para landings públicas.
 * Vive en _stock porque las landings no cargan toozle.css.
 * Colores vía variables: --whatsapp, --whatsapp-hover, --whatsapp-pulse.
 * ========================================= */

.whatsapp-sticky-button {
  position: fixed;
  bottom: 30px;
  right: 30px;
  width: 60px;
  height: 60px;
  /* sesión 2026-05-10: el sticky consume su propia var. Permite color
     distinto al CTA del hero. Default: verde stock. */
  background-color: var(--whatsapp-floating);
  color: #ffffff !important;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.75rem;
  text-decoration: none;
  box-shadow: 0 4px 12px var(--whatsapp-pulse);
  z-index: 9999;
  transition: transform 0.3s ease, background-color 0.3s ease;
  animation: whatsapp-pulse 2s infinite;
}

.whatsapp-sticky-button:hover,
.whatsapp-sticky-button:focus {
  background-color: var(--whatsapp-floating-hover);
  color: #ffffff !important;
  transform: scale(1.1);
  text-decoration: none;
}

.whatsapp-sticky-button i {
  color: #ffffff !important;
  line-height: 1;
}

@keyframes whatsapp-pulse {
  0%   { box-shadow: 0 0 0 0 var(--whatsapp-pulse); }
  70%  { box-shadow: 0 0 0 20px rgba(37, 211, 102, 0); }
  100% { box-shadow: 0 0 0 0 rgba(37, 211, 102, 0); }
}

@media (max-width: 768px) {
  .whatsapp-sticky-button {
    width: 50px;
    height: 50px;
    bottom: 20px;
    right: 20px;
    font-size: 1.5rem;
  }

  @keyframes whatsapp-pulse {
    0%   { box-shadow: 0 0 0 0 var(--whatsapp-pulse); }
    70%  { box-shadow: 0 0 0 15px rgba(37, 211, 102, 0); }
    100% { box-shadow: 0 0 0 0 rgba(37, 211, 102, 0); }
  }
}
/* ═══════════════════════════════════════════════════════════════════════════
   THANKS — Página de gracias post-formulario (page-gracias.php)
   ═══════════════════════════════════════════════════════════════════════════
   La sección usa .hero is-dark + .thanks-section. NO usa .section-gradient
   (esa clase pertenece al theme institucional Landing+ — ver §22.7 del
   MAESTRO). El fondo lo resuelve esta misma regla con un gradiente vertical
   derivado de --primary del cliente, así cada landing muestra la paleta
   correcta en su page de gracias.

   La técnica: color-mix() mezcla --primary con negro (top, 8%) y blanco
   (bottom, 30%) para generar dos paradas del mismo color en distintas
   luminosidades. Funciona con cualquier --primary (azul, verde, naranja,
   etc.) sin que cada cliente tenga que definir nada extra. Soporte
   browser: todos los modernos desde 2023 (Chrome 111+, Safari 16.2+,
   Firefox 113+).

   Fallback para browsers viejos: si color-mix no se soporta, la regla
   anterior sigue aplicando (var(--primary) plano) — degradación elegante.
   ─────────────────────────────────────────────────────────────────────────── */

.thanks-section {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--primary);
  background-image: linear-gradient(
    180deg,
    color-mix(in srgb, var(--primary) 92%, #000 8%) 0%,
    color-mix(in srgb, var(--primary) 70%, #fff 30%) 100%
  );
  color: var(--white);
}

.thanks-section .thanks-icon {
  font-size: 9rem;
  line-height: 1;
  margin-bottom: 1.5rem;
  color: rgba(255, 255, 255, 0.95);
}

@media (max-width: 576px) {
  .thanks-section .thanks-icon {
    font-size: 6rem;
    margin-bottom: 1rem;
  }
}
/* ═══════════════════════════════════════════════════════════════════════
 * BLOCK BUILDER — clases adicionales
 * Pegar al final de _stock/assets/base.css o cargar como archivo aparte.
 *
 * Reutiliza variables existentes (--primary, --light, --dark, etc.) del
 * colors.css del sistema. No introduce paleta nueva.
 *
 * Cubre:
 *   - tlp-py-* : paddings verticales (compacto/normal/amplio)
 *   - tlp-card-white/dark : variantes de card que no estaban
 *   - card-image : wrapper de imagen dentro de una card
 *   - tlp-pricing-highlighted : plan destacado
 *   - tlp-masonry : galería masonry
 * ═══════════════════════════════════════════════════════════════════════ */

/* ── Paddings verticales del bloque ───────────────────────────────────── */
/*  El padding default de .section es 88px. Estas variantes lo reemplazan. */
.section.tlp-py-compact,
.hero.tlp-py-compact {
  padding-top: 48px;
  padding-bottom: 48px;
}

.section.tlp-py-normal,
.hero.tlp-py-normal {
  padding-top: 88px;
  padding-bottom: 88px;
}

.section.tlp-py-wide,
.hero.tlp-py-wide {
  padding-top: 128px;
  padding-bottom: 128px;
}

/* Sesion 2026-05-28: padding XL. Solo aplica al hero (no a .section). El hero
   ocupa cuasi pantalla completa (min-height 90vh) y el contenido se centra
   verticalmente. Usar cuando la imagen de fondo necesita protagonismo. */
.hero.tlp-py-xl {
  min-height: 90vh;
  padding-top: 120px;
  padding-bottom: 120px;
  display: flex;
  align-items: center;
}
.hero.tlp-py-xl > .container {
  width: 100%;
}

@media (max-width: 768px) {
  .section.tlp-py-compact,
  .hero.tlp-py-compact    { padding-top: 32px;  padding-bottom: 32px; }
  .section.tlp-py-normal,
  .hero.tlp-py-normal     { padding-top: 56px;  padding-bottom: 56px; }
  .section.tlp-py-wide,
  .hero.tlp-py-wide       { padding-top: 80px;  padding-bottom: 80px; }
  .hero.tlp-py-xl         { min-height: auto; padding-top: 96px; padding-bottom: 96px; display: block; }
}

/* ── Variantes de card individuales (la primary y soft ya existen) ─────── */
.tlp-card-white {
  background: var(--white) !important;
  color: var(--text);
}

.tlp-card-dark {
  background: var(--dark) !important;
  color: #ffffff;
  border-color: rgba(255, 255, 255, 0.12);
}

.tlp-card-dark h1,
.tlp-card-dark h2,
.tlp-card-dark h3,
.tlp-card-dark h4,
.tlp-card-dark h5,
.tlp-card-dark h6 {
  color: #ffffff;
}

.tlp-card-dark .tlp-muted {
  color: rgba(255, 255, 255, 0.74);
}

.tlp-card-dark .icon-circle {
  background: rgba(255, 255, 255, 0.12);
  color: #ffffff;
}

/* ── Imagen dentro de card ────────────────────────────────────────────── */
/* Sesión 2026-05-08 (cierre): la imagen va FLUSH al borde de la card.
   Con margin negativo solo se desplaza la posición — el ancho del elemento
   sigue siendo el ancho del flex-item (card_width - padding). Para que
   ocupe el ancho REAL de la card (incluyendo el padding y el border)
   necesitamos width:calc(100% + 58px) = 100% + 28*2 padding + 1*2 border.
   El margin negativo ahí solo lo posiciona en (-29, -29). */
.card-clean:has(.card-image) {
  overflow: hidden;
}

.card-clean .card-image {
  width: calc(100% + 58px);
  margin: -29px -29px 1rem -29px;
  overflow: hidden;
  aspect-ratio: 16 / 10;
  background: var(--light);
}

.card-clean .card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ── Pricing destacado ────────────────────────────────────────────────── */
.tlp-pricing-highlighted {
  border-color: var(--primary) !important;
  box-shadow: 0 18px 50px var(--primary-shadow);
  position: relative;
}

@media (min-width: 992px) {
  .tlp-pricing-highlighted {
    transform: translateY(-12px);
  }
}

/* ── Galería masonry ──────────────────────────────────────────────────── */
.tlp-masonry {
  column-count: 3;
  column-gap: 1rem;
}

.tlp-masonry > * {
  break-inside: avoid;
  margin-bottom: 1rem;
}

@media (max-width: 768px) {
  .tlp-masonry { column-count: 2; }
}

@media (max-width: 480px) {
  .tlp-masonry { column-count: 1; }
}

/* ── Section context: cuando section-bg-primary o section-bg-dark están  */
/*    sin .is-dark se refuerza el contraste del texto                     */
.section-bg-primary:not(.is-dark),
.section-bg-dark:not(.is-dark) {
  /* fallback por si no se aplicó la regla del registry */
  color: #ffffff;
}

.section-bg-primary:not(.is-dark) h1,
.section-bg-primary:not(.is-dark) h2,
.section-bg-primary:not(.is-dark) h3,
.section-bg-dark:not(.is-dark) h1,
.section-bg-dark:not(.is-dark) h2,
.section-bg-dark:not(.is-dark) h3 {
  color: #ffffff;
}

/* ═════════════════════════════════════════════════════════════════════════
   BLOCK BUILDER · features sumadas en sesión 2026-05-06
   ═════════════════════════════════════════════════════════════════════════ */

/* ── Sombras en cards del bloque (toggle a nivel bloque entero) ─────────── */
/* Se activa con el toggle "Sombra en cards" en el panel Estilo del editor.
   El render emite la clase tlp-cards-shadow en el <section> wrapper.
   Aplica a todas las card-clean adentro, parejo. */
.tlp-cards-shadow .card-clean {
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06), 0 2px 6px rgba(0, 0, 0, 0.04);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.tlp-cards-shadow .card-clean:hover {
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.10), 0 4px 10px rgba(0, 0, 0, 0.05);
  transform: translateY(-2px);
}

/* En contextos oscuros la sombra se refuerza con un halo claro arriba */
.section-bg-dark.tlp-cards-shadow .card-clean,
.section-bg-primary.tlp-cards-shadow .card-clean {
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.20), 0 2px 6px rgba(0, 0, 0, 0.15);
}

/* ── Strip de logos / sellos / press (layout info_logos_strip) ─────────── */
/* Sesión 2026-05-08 (cierre): se reemplazó el contenedor flex por un row de
   Bootstrap (col-6 col-md-3 = 4 por fila). Las reglas de .tlp-logos-strip
   ya no se usan — el partial info_logos_strip rendea con .row directamente. */

.tlp-logos-strip-item {
  width: 100%;
}

/* Sesión 2026-05-08 (cierre): contenedor grande que ocupa el ancho de la
   columna del grid (~16% del row con 6 columnas). El logo se centra adentro
   con max-height y filter:grayscale. Aspect 4/3 para que cuadre prolijo
   con cualquier proporción de logo (cuadrado, horizontal o vertical). */
.tlp-logos-strip-frame {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: rgba(0, 0, 0, 0.02);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: 8px;
  padding: 20px;
}

.tlp-logos-strip-img {
  max-height: 100%;
  max-width: 100%;
  width: auto;
  height: auto;
  filter: grayscale(100%);
  opacity: 0.6;
  transition: filter 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
}

.tlp-logos-strip-item:hover .tlp-logos-strip-img,
.tlp-logos-strip-item a:hover .tlp-logos-strip-img {
  filter: grayscale(0%);
  opacity: 1;
}

.tlp-logos-strip-label {
  color: var(--muted);
}

.section-bg-dark .tlp-logos-strip-frame,
.section-bg-primary.is-dark .tlp-logos-strip-frame {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.10);
}

.section-bg-dark .tlp-logos-strip-img,
.section-bg-primary.is-dark .tlp-logos-strip-img {
  filter: grayscale(100%) brightness(0) invert(1);
  opacity: 0.7;
}

.section-bg-dark .tlp-logos-strip-item:hover .tlp-logos-strip-img,
.section-bg-dark .tlp-logos-strip-item a:hover .tlp-logos-strip-img,
.section-bg-primary.is-dark .tlp-logos-strip-item:hover .tlp-logos-strip-img,
.section-bg-primary.is-dark .tlp-logos-strip-item a:hover .tlp-logos-strip-img {
  filter: grayscale(0%) brightness(1) invert(0);
  opacity: 1;
}

@media (max-width: 600px) {
  .tlp-logos-strip-frame { padding: 12px; }
}

/* ── Mapa: tamaños proporcionales del iframe ────────────────────────────── */
/* Sesión 2026-05-14: el extra_block_field `size` del bloque map_embed       */
/* aplica una de estas tres clases al wrapper. `full` ocupa todo el ancho    */
/* del container (default histórico). `large` y `medium` centran el mapa     */
/* con un max-width — útil cuando una landing usa el mapa como referencia    */
/* visual y no quiere que ocupe toda la sección.                              */
/*                                                                            */
/* No aplica a map_split: en split el tamaño del mapa lo decide el grid       */
/* (col-lg-7 de Bootstrap), no este modificador.                              */
.tlp-map-size-full {
  width: 100%;
}

.tlp-map-size-large {
  max-width: 1000px;
  margin-left: auto;
  margin-right: auto;
}

.tlp-map-size-medium {
  max-width: 760px;
  margin-left: auto;
  margin-right: auto;
}

/* ── Galería: modo flush (toggle "sin padding" del bloque) ──────────────── */
/* Sesión 2026-05-14: cuando el operador prende el toggle no_padding en un  */
/* bloque gallery_grid / gallery_grid_8, la card de cada imagen pierde su  */
/* padding interno y el thumb queda pegado a los 4 bordes. La card mantiene */
/* su border-radius — `overflow: hidden` recorta la imagen contra ese radius */
/* (las esquinas del thumb siguen el contorno redondeado).                   */
/*                                                                            */
/* Si hay captions prendidos, viven adentro de .tlp-gallery-caption-wrap     */
/* que les da un padding propio para no pegar al borde del thumb. El partial */
/* solo emite ese wrapper en modo flush — el render canónico no lo lleva.    */
.card-clean.tlp-gallery-flush {
  padding: 0 !important;
  overflow: hidden;
}

.tlp-gallery-flush .tlp-gallery-caption-wrap {
  padding: 1rem 1.25rem 1.25rem;
}

/* Sesión 2026-06-05: controles globales de la galería.                      */
/* Grosor del borde (solo aplica si el borde no es none) y esquinas rectas. */
.card-clean.tlp-gallery-bw-2 {
  border-width: 2px;
}

.card-clean.tlp-gallery-bw-3 {
  border-width: 3px;
}

.card-clean.tlp-gallery-square,
.tlp-gallery-square .ratio {
  border-radius: 0 !important;
}

/* ── tlp-badge-soft-inverse — badge para contexto cromático oscuro ────────── */
/*                                                                             */
/*  Sesión 2026-05-07: el partial _card-universal.php usa esta clase cuando   */
/*  la card termina en contexto dark — sea por color de card primary/dark, o  */
/*  por card 'inherit' adentro de una sección primary/dark.                   */
/*  En sección oscura con card 'inherit', .tlp-badge-soft ya se adapta vía    */
/*  vars CSS, así que esta clase solo es necesaria cuando la CARD pisa el     */
/*  contexto (caso "card destacada en bloque claro").                         */

.tlp-badge-soft-inverse {
  display: inline-block;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.18);
  color: #ffffff;
  font-size: 0.78rem;
  font-weight: 700;
}

/* ── Fix: tlp-muted dentro de tlp-card-primary ────────────────────────────── */
/*                                                                             */
/*  Sesión 2026-05-07: paridad con .tlp-card-dark .tlp-muted (línea ~1601).   */
/*  .tlp-card-primary aplica color: #ffffff !important al elemento card pero  */
/*  el <p class="tlp-muted"> hijo tiene su propia regla (var(--muted) gris)   */
/*  que NO se rebaja al heredar dentro de la card primary. Resultado:         */
/*  texto gris poco legible sobre fondo azul. Esta regla lo arregla.          */

.tlp-card-primary .tlp-muted {
  color: rgba(255, 255, 255, 0.75);
}

/* === Trust list: ícono primary, mismo patrón que .pricing-list i ========
   Color del ícono según contexto cromático (sesión 2026-05-08 rev3):
   - Default (light): primary
   - Card primary o sección dark: blanco. */
.tlp-trust-list {
  list-style: none;
  padding: 0;
}

.tlp-trust-list li {
  color: var(--muted);
}

.tlp-trust-list i {
  color: var(--primary);
}

/* Sesión 2026-05-12: trust-list y pricing-list dependen del contexto de la
   card que los contiene, no de la sección. */

.tlp-card-context-dark .tlp-trust-list li {
  color: rgba(255, 255, 255, 0.74);
}

.tlp-card-context-dark .tlp-trust-list i {
  color: #ffffff;
}

.tlp-card-context-light .tlp-trust-list li {
  color: var(--muted);
}

.tlp-card-context-light .tlp-trust-list i {
  color: var(--primary);
}

/* Trust list dentro del HEADER del bloque sobre sección primary o dark.       */
/* (Sesión 2026-05-14): la trust-list del header no está envuelta en una card, */
/* así que las reglas de .tlp-card-context-* no la alcanzan. Para mantener     */
/* paridad cromática (ícono blanco en fondos oscuros), targetear el header    */
/* del bloque adentro de .is-dark. No afecta cards: las cards adentro de la   */
/* sección oscura tienen su propio .tlp-card-context-* y nunca caen adentro   */
/* de .section-header / .tlp-block-header-inline.                              */
.is-dark .section-header .tlp-trust-list i,
.is-dark .tlp-block-header-inline .tlp-trust-list i {
  color: #ffffff;
}

.is-dark .section-header .tlp-trust-list li,
.is-dark .tlp-block-header-inline .tlp-trust-list li {
  color: rgba(255, 255, 255, 0.85);
}

/* Sesión 2026-06-11: en el bloque Imagen+texto (professional) el header inline
   —subtítulo (p) + trust list— vive DENTRO de la card, no en el header de
   sección. Las reglas .is-dark .tlp-block-header-inline de arriba pintan ese
   contenido según la SECCIÓN: con una card clara dentro de una sección oscura
   (ej. card blanca en sección roja) el subtítulo y los trust items quedaban
   blancos sobre fondo claro → ilegibles. Acá manda el contexto de la card:
   selector con 4 clases que gana a las reglas de sección (3 clases) en todas
   las variantes. El título (h2) y la bio ya leen var(--text), que la card
   redefine, por eso esos sí se veían. */
.professional-profile-card.tlp-card-context-light .tlp-block-header-inline p {
  color: var(--muted);
}
.professional-profile-card.tlp-card-context-light .tlp-block-header-inline .tlp-trust-list i {
  color: var(--primary);
}
.professional-profile-card.tlp-card-context-light .tlp-block-header-inline .tlp-trust-list li {
  color: var(--muted);
}
.professional-profile-card.tlp-card-context-dark .tlp-block-header-inline p {
  color: rgba(255, 255, 255, 0.74);
}
.professional-profile-card.tlp-card-context-dark .tlp-block-header-inline .tlp-trust-list i {
  color: #ffffff;
}
.professional-profile-card.tlp-card-context-dark .tlp-block-header-inline .tlp-trust-list li {
  color: rgba(255, 255, 255, 0.85);
}

/* ──────────────────────────────────────────────────────────────────────────
   Color custom para eyebrow / badge / trust-item (sesión 2026-05-13)
   ──────────────────────────────────────────────────────────────────────────
   El operador puede pintar el ícono + texto de un eyebrow, badge o trust-item
   con un color preset (primary/dark/success/etc) o un hex libre. El PHP emite
   inline `style="color: X;"` en el elemento contenedor.

   Como los íconos dentro de eyebrow/badge/trust-list tienen reglas CSS propias
   con clase selector (que ganan a la herencia), forzamos `color: inherit` en
   esos íconos cuando el contenedor tiene inline color. El selector usa el
   atributo `[style*="color"]` que matchea cualquier color inline declarado.
   ────────────────────────────────────────────────────────────────────────── */

.eyebrow[style*="color"] i {
  color: inherit;
}

.tlp-badge-soft[style*="color"] i,
.tlp-badge-soft-inverse[style*="color"] i {
  color: inherit;
}

/* Sesión 2026-05-13 rev5: igual para el .hero-badge — cuando hay inline color
   en el chip, el ícono hereda en lugar de quedarse con el color canon. */
.hero-badge[style*="color"] i {
  color: inherit;
}

.tlp-trust-list li[style*="color"] i,
.tlp-trust-list li[style*="color"] span {
  color: inherit;
}

/* En contextos dark, mismo principio — la regla específica del contexto sigue
   ganando si NO hay inline color. Si hay inline color, inherit toma el valor
   inline del <li>. Para que esto funcione, el override de contexto dark del
   ícono no se aplica cuando el <li> tiene inline color. */
.tlp-card-context-dark .tlp-trust-list li[style*="color"] i {
  color: inherit;
}

/* === Header del builder en modo inline ================================== */
/*
   Cuando un partial usa _block-header.php con $header_inline = true (caso
   típico: info/split.php, cta/split.php), el wrapper .section-header NO se
   aplica. Esta clase replica los espaciados y tamaños canónicos de
   .section-header h2 / .section-header p para que el header inline se vea
   con el mismo "peso visual" que un section-header normal — solo cambia
   que no centra el contenido (lo decide el caller) ni limita ancho.
*/
.tlp-block-header-inline .eyebrow {
  margin-bottom: 14px;
}

.tlp-block-header-inline h2 {
  margin: 0 0 14px;
  font-size: clamp(2rem, 4vw, 2.5rem);
  line-height: 1.2;
  font-weight: 700;
}

.tlp-block-header-inline p {
  margin-bottom: 18px;
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1.75;
}

.tlp-block-header-inline .d-flex.gap-3 {
  margin-top: 18px;
}

.is-dark .tlp-block-header-inline p {
  color: rgba(255, 255, 255, 0.74);
}


/* ============================================================
   MODAL DE CAPTURA DE NOMBRE (WhatsApp) — sesión 2026-05-17
   ============================================================
   Modal compacto disparado por cualquier botón con
   data-lp-capture-form="1". Captura Nombre, crea Lead vía
   landing_plus_capture_whatsapp_lead y al éxito redirige a
   WhatsApp directo (web.whatsapp.com/send).

   Scope estricto a `.tlp-whatsapp-capture-modal` para no
   colisionar con `.tlp-form-popup-modal` (otro modal canon).
   El botón submit usa `var(--whatsapp-cta)` (tab Estilos
   per-landing puede overridear), fallback verde stock #25D366.
*/
.tlp-whatsapp-capture-modal .modal-dialog {
  max-width: 420px;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-card {
  position: relative;
  border-radius: 18px;
  border: 0;
  overflow: hidden;
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.18);
  text-align: center;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 5;
  background-color: rgba(0, 0, 0, 0.04);
  border-radius: 50%;
  padding: 8px;
  opacity: 0.7;
  transition: opacity 120ms ease, background-color 120ms ease;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-close:hover {
  opacity: 1;
  background-color: rgba(0, 0, 0, 0.08);
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  margin: 0 auto 18px;
  background-color: var(--whatsapp-cta, #25D366);
  color: #fff;
  border-radius: 50%;
  font-size: 32px;
  box-shadow: 0 6px 18px rgba(37, 211, 102, 0.25);
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-icon i {
  line-height: 1;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-title {
  font-size: 1.35rem;
  font-weight: 700;
  margin: 0 0 6px;
  line-height: 1.25;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-lead {
  font-size: 0.95rem;
  color: #555;
  margin: 0 0 18px;
  line-height: 1.45;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-input {
  border-radius: 12px;
  border: 1px solid rgba(0, 0, 0, 0.12);
  padding: 12px 14px;
  font-size: 1rem;
  text-align: center;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-input:focus {
  border-color: var(--primary, #0d6efd);
  box-shadow: 0 0 0 0.2rem var(--primary-alpha-18, rgba(13, 110, 253, 0.18));
  outline: 0;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background-color: var(--whatsapp-cta, #25D366);
  color: #fff;
  font-weight: 600;
  font-size: 1rem;
  border: 0;
  border-radius: 12px;
  padding: 12px 18px;
  cursor: pointer;
  transition: background-color 120ms ease, transform 120ms ease, opacity 120ms ease;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-submit:hover {
  background-color: var(--whatsapp-cta-hover, #1ebe5b);
  transform: translateY(-1px);
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-submit:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-submit i {
  font-size: 1.15rem;
  line-height: 1;
}

.tlp-whatsapp-capture-modal .tlp-whatsapp-capture-error {
  margin: 0;
  padding: 8px 12px;
  font-size: 0.875rem;
  color: #b00020;
  background-color: rgba(176, 0, 32, 0.08);
  border-radius: 8px;
  text-align: center;
}


/* ───────────────────────────────────────────────────────────────────
 * PRICING CARD: badge flotante + period en linea propia (sesion 2026-05-28)
 * Aplica al partial builder/_card-pricing.php (Builder de bloques).
 * .pricing-card-flag posicionado absolute sobre el borde superior de la
 * card (paridad con .pricing-box-flag del theme institucional).
 *
 * Variantes (fondo solido, colores hardcoded para evitar herencias dark
 * que vuelvan invisible el texto contra el fondo de la pill):
 *   default  → primary solido + texto blanco (para cards light)
 *   .is-light → blanco solido + texto #212529 (para cards dark)
 *   .is-dark  → #212529 solido + texto blanco (alternativa para cards light)
 * ─────────────────────────────────────────────────────────────────── */
.pricing-card { position: relative; overflow: visible; }
.pricing-card.is-featured { overflow: visible; }
.pricing-card-flag {
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--primary, #036D75);
  color: #ffffff;
  font-size: .75rem;
  font-weight: 700;
  padding: .35rem .9rem;
  border-radius: 999px;
  letter-spacing: .02em;
  white-space: nowrap;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .15);
  z-index: 2;
}
.pricing-card-flag.is-light {
  background: #ffffff;
  color: #212529;
  border: 1px solid rgba(0, 0, 0, 0.06);
  box-shadow: 0 4px 12px rgba(0, 0, 0, .18);
}
.pricing-card-flag.is-dark {
  background: #212529;
  color: #ffffff;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .25);
}
.pricing-price-period {
  font-size: .95rem;
  font-weight: 600;
  color: var(--muted, #6c757d);
  margin-top: -.5rem;
  margin-bottom: 1rem;
  line-height: 1.2;
}
