/* ==========================================================================
   Fase 5 Audit Fixes — sesión 2026-06-11
   Consolidado de hallazgos auditoría visual D11 dev (5 breakpoints).
   Cada bloque referencia ID de hallazgo en docs/auditoria-fase5-2026-06-11.md.
   Mobile-first. Sin !important salvo justificación inline.
   ========================================================================== */


/* --------------------------------------------------------------------------
   P1 — Overflows / ilegibilidad / roto
   -------------------------------------------------------------------------- */

/* ==========================================================================
   CLÚSTER A — Header global: hamburguesa fuera de viewport a 360 y CTA
   cortado en el rango con nav inline (769–1199px).
   IDs: P1-campamentos_gredos-003, P1-campamentos_tarifa-001, P1-campamentos_tarifa-002,
   P1-campamentos_curso-...-001, P1-campamentos_sotogrande-001, P1-campamentos_sotogrande-002,
   P1-campamentos_kids-camp-001, P1-campamentos_kids-camp-002, P1-noticias-001,
   P1-campamentos_toledo-001, P1-user-001, P1-campamentos_verano-001,
   P1-campamentos_layoscamp-santander-...-001, P1-campamentos_toledo-junior (header),
   P1-cart-001, P1-equipo-001.

   DOM verificado en dev (2026-06-12): .site-header > .header-inner con
   .header-logo / .header-nav / .header-actions (.header-lang + .btn.btn--gold
   + .header-hamburger). El CTA lleva style= inline en page.html.twig
   (padding: 10px 20px; font-size: 0.875rem) -> los !important de este bloque
   son para vencer ESE inline (Twig prohibido en este lote). El corte real
   nav<->hamburguesa es @media (max-width: 768px) en design-system-v2.css
   (no 992 como estimaba la auditoría).
   ========================================================================== */

/* Base mobile (360): compactar logo + CTA para que logo + CTA + hamburguesa
   quepan en 360px con la hamburguesa SIEMPRE dentro del viewport. */
.site-header .header-inner {
  padding: 0 12px;
  gap: 10px;
}
.site-header .header-logo { gap: 6px; }
.site-header .header-logo__name { font-size: 1rem; }
.site-header .header-actions { gap: 8px; }
/* !important: vence el style= inline del CTA en page.html.twig */
.site-header .header-actions .btn.btn--gold {
  padding: 8px 10px !important;
  font-size: 0.75rem !important;
}
.site-header .header-actions .btn.btn--gold .material-icons {
  font-size: 14px !important; /* idem: inline style="font-size:16px" en el Twig */
}
/* Tap target AA >= 44px y sin colapso dentro del flex row */
.site-header .header-hamburger {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
}

/* >=576px: restaurar exactamente los valores del inline del Twig
   (cero cambio visual respecto a hoy fuera de los rangos acotados de abajo). */
@media (min-width: 576px) {
  .site-header .header-inner {
    padding: 0 24px;
    gap: 24px;
  }
  .site-header .header-logo { gap: 10px; }
  .site-header .header-logo__name { font-size: 1.25rem; }
  .site-header .header-actions { gap: 10px; }
  .site-header .header-actions .btn.btn--gold {
    padding: 10px 20px !important; /* = inline del Twig */
    font-size: 0.875rem !important;
  }
  .site-header .header-actions .btn.btn--gold .material-icons {
    font-size: 16px !important; /* = inline del Twig */
  }
}

/* Rango acotado 769–991px — JUSTIFICACIÓN de la excepción mobile-first:
   design-system-v2.css (legacy) pasa la nav a inline desde >768px, y a ese
   ancho los 6 links + CTA no caben. Subir el corte de la hamburguesa a 1200
   no es viable en CSS puro: el botón hamburguesa NO tiene drawer ni handler
   JS (es inerte), ocultar la nav inline aquí dejaría el sitio sin navegación.
   La única salida CSS es comprimir en la banda exacta del problema; el rango
   expira en 992 y no contamina la base mobile (que sigue siendo aditiva). */
@media (min-width: 769px) and (max-width: 991.98px) {
  .site-header .header-inner {
    padding: 0 12px;
    gap: 10px;
  }
  .site-header .header-logo__name { font-size: 1rem; }
  .site-header .header-nav { gap: 0; }
  .site-header .nav-link {
    font-size: 0.75rem;
    padding: 8px 5px;
    white-space: nowrap; /* evita 'Curso de monitores' en 2 lineas (P1-campamentos_tarifa-002) */
  }
  .site-header .header-actions { gap: 8px; }
  /* Coherente con mobile: el idioma ya va oculto <=768 en design-system-v2.css */
  .site-header .header-actions .header-lang { display: none; }
  .site-header .header-actions .btn.btn--gold {
    padding: 8px 10px !important; /* vence inline del Twig */
    font-size: 0.75rem !important;
  }
  .site-header .header-actions .btn.btn--gold .material-icons {
    font-size: 14px !important;
  }
}

/* Rango acotado 992–1199px — misma justificación que el bloque anterior:
   a 1024 la nav inline + EN + CTA suman mas que el viewport y el CTA quedaba
   cortado en x=1033 (P1-campamentos_gredos-003 et al.). Compresion ligera. */
@media (min-width: 992px) and (max-width: 1199.98px) {
  .site-header .header-inner {
    padding: 0 16px;
    gap: 12px;
  }
  .site-header .header-nav { gap: 0; }
  .site-header .nav-link {
    font-size: 0.8125rem;
    padding: 8px 8px;
    white-space: nowrap;
  }
  .site-header .header-actions { gap: 8px; }
  .site-header .header-actions .btn.btn--gold {
    padding: 8px 14px !important; /* vence inline del Twig */
    font-size: 0.8125rem !important;
  }
}

/* ==========================================================================
   CLÚSTER B — Precio dorado sobre blanco en la sticky bar de reserva mobile.
   IDs: P1-campamentos_curso-...-002, P1-campamentos_toledo-junior-001.
   DOM verificado en dev: .camp-detail__cta-sticky > .camp-detail__cta-sticky-price
   (la auditoría estimaba .sticky-reserve .price — no existe). La regla a vencer
   es design-system-v2-extras.css:217 { color: var(--gold) } — misma
   especificidad, este archivo carga después (weight 200).
   ========================================================================== */
.camp-detail__cta-sticky-price {
  color: var(--green-dark, #2D5016); /* 9.4:1 sobre blanco; dorado reservado al boton Reservar */
}

/* ==========================================================================
   CLÚSTER C — Links de cuerpo legal en verde claro #8BA841 sobre blanco (~2.6:1).
   IDs: P1-politica-de-cookies-001, P2-politica-de-privacidad-001.
   DOM verificado en dev: cookies usa .E-page-body__text (regla a vencer:
   style.css:22108 .E-page-body__text a { color:#8BA841 }); privacidad usa
   .page-content__body. En privacidad los links son VERDES en vivo, no dorados
   como estimó la auditoría. P2-politica-de-privacidad-002 (heading dorado)
   NO reproducible en vivo -> sin regla.
   ========================================================================== */
.E-page-body__text a,
.page-content__body a {
  color: var(--green-medium, #3D6B1E); /* 6.0:1 sobre blanco, AA texto de cuerpo */
  text-decoration: underline;
  text-underline-offset: 2px;
}
.E-page-body__text a:hover,
.E-page-body__text a:focus,
.page-content__body a:hover,
.page-content__body a:focus {
  color: var(--green-dark, #2D5016);
}

/* ==========================================================================
   CLÚSTER J — Contacto: labels y textos de consentimiento RGPD en blanco
   sobre panel verde pálido #F0F4E8 (ilegibles).
   ID: P1-contacto-001.
   DOM verificado en dev: el blanco viene de style.css
   `.page-node-type-contacto legend, .page-node-type-contacto
   label.js-form-required.form-required { color: white }` (especificidad 0-3-1,
   herencia del antiguo diseño con fondo verde oscuro). Se replica el selector
   exacto para empatar especificidad y ganar por orden de carga.
   Las descripciones RGPD (12px) heredaban el blanco -> regla directa.
   ========================================================================== */
.page-node-type-contacto label.js-form-required.form-required,
.page-node-type-contacto .webform-submission-form label {
  color: var(--text, #1A1A1A);
  /* !important: vence a style.css legacy `form .form-type-textfield label...
     { font-weight: 500 !important }` (style.css es intocable por regla del proyecto) */
  font-weight: 600 !important; /* Inter ya es la familia del form */
}
.page-node-type-contacto legend {
  color: var(--green-dark, #2D5016);
  font-weight: 600;
}
.page-node-type-contacto .webform-submission-form .webform-element-description,
.page-node-type-contacto .webform-submission-form .description {
  color: var(--text-sec, #555555); /* 6.4:1 sobre #F0F4E8 */
  font-size: 0.8125rem; /* >=13px (antes 12px) */
  line-height: 1.5;
}

/* ==========================================================================
   CLÚSTER O — Noticias: titulares largos desbordan el scrim blanco y caen
   en #31562D directamente sobre la foto.
   ID: P1-noticias-002.
   DOM verificado en dev: article.E-noticia-teaser > a > div.G-fondo--degra-abajo-blanco
   (min-height:260px inline) > h2.G-color--primario. Scrim actual (style.css):
   linear-gradient(0deg, rgba(255,255,255,.95) 0%, rgba(255,255,255,.6) 40%,
   transparent 100%) — a partir del 40% ya es translucido.
   ========================================================================== */
.E-noticia-teaser .G-fondo--degra-abajo-blanco {
  /* Scrim mas alto y opaco: zona >=0.93 cubre 3 lineas de titular */
  background-image: linear-gradient(
    0deg,
    rgba(255, 255, 255, 0.97) 0%,
    rgba(255, 255, 255, 0.93) 45%,
    rgba(255, 255, 255, 0.55) 72%,
    rgba(255, 255, 255, 0) 100%
  );
}
.E-noticia-teaser h2 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}

/* ==========================================================================
   CLÚSTER D/E — Gredos: hero "apagado" (P1-campamentos_gredos-001) y banda
   gris #808080 (P1-campamentos_gredos-002).
   VEREDICTO: no-fix-artifact. Verificado en vivo 2026-06-12 a 1440 y 2560 con
   el banner de cookies CERRADO: H1 #FFFFFF opacity 1, overlay
   .camp-detail__hero-overlay con z-index 1 detras del contenido, cero
   elementos con fondo ~#808080. El gris de las capturas de la auditoria era
   el backdrop del banner EU Cookie Compliance en el stitch full-page.
   NO añadir reglas para estos dos IDs.
   ========================================================================== */


/* --------------------------------------------------------------------------
   P2 — Fuera de marca
   -------------------------------------------------------------------------- */

/* ==========================================================================
   CLÚSTER H — Demotion del dorado en CTAs secundarios (dorado SOLO
   transaccional, decisión Design Director). Patrón: CTA secundario = OUTLINE
   (blanco sobre fondo oscuro, verde #8BA841 + texto #2D5016 sobre claro).
   IDs: P2-campamentos_tarifa-005, P2-campamentos_curso-...-008,
   P2-campamentos_sotogrande-005, P2-campamentos_kids-camp-006,
   P2-campamentos_toledo-junior-006, P2-home-003, P2-noticias-004,
   P2-cart-005, P2-equipo-004, P2-preguntas-frecuentes-004,
   P3-campamentos_verano-010, P2-campamentos_toledo-003 (parte 'Ver todas
   las fechas'; la parte modal va en el clúster G).
   DOM verificado en dev (2026-06-12): footer global = .site-footer .btn--gold
   ('Contactar ahora', gradiente dorado computado en vivo); sidebar ficha =
   .camp-detail__sidebar-card .btn--gold ('Ver todas las fechas'); FAQ =
   .faq-v2__contact .btn--gold; colegios = .colegios-v2__cta-banner .btn--gold
   ('Solicitar propuesta', incluido por decisión DD explícita).
   .btn base ya trae border: 2px solid transparent -> basta border-color.
   ========================================================================== */

/* Footer global (fondo oscuro #1A1A1A): outline blanco.
   !important en color/border: vence `.btn--gold { color:#2D5016 !important }`
   del design-system-v2.css DESPLEGADO en dev (drift Kimi vs repo, verificado
   en vivo 2026-06-12) que además deja el border a 0. */
.site-footer .btn.btn--gold {
  background: transparent;
  border: 2px solid rgba(255, 255, 255, 0.85) !important;
  color: #fff !important;
  box-shadow: none;
}
.site-footer .btn.btn--gold:hover,
.site-footer .btn.btn--gold:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  border-color: #fff !important;
  color: #fff !important;
  box-shadow: none;
  filter: none;
}

/* Banner CTA colegios (fondo --green-dark): outline blanco (mismos
   !important que el footer, misma regla drift a vencer) */
.colegios-v2__cta-banner .btn.btn--gold {
  background: transparent;
  border: 2px solid rgba(255, 255, 255, 0.85) !important;
  color: #fff !important;
  box-shadow: none;
}
.colegios-v2__cta-banner .btn.btn--gold:hover,
.colegios-v2__cta-banner .btn.btn--gold:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  border-color: #fff !important;
  color: #fff !important;
  box-shadow: none;
  filter: none;
}

/* Superficies claras (sidebar ficha #F0F4E8, caja contacto FAQ --green-bg):
   outline verde brand + texto verde oscuro (9.4:1 sobre claro).
   border con !important por el mismo drift (el color #2D5016 ya coincide
   con el !important del drift, no hace falta pelearlo). */
.camp-detail__sidebar-card .btn.btn--gold,
.faq-v2__contact .btn.btn--gold {
  background: transparent;
  border: 2px solid var(--green-brand, #8BA841) !important;
  color: var(--green-dark, #2D5016);
  box-shadow: none;
}
.camp-detail__sidebar-card .btn.btn--gold:hover,
.camp-detail__sidebar-card .btn.btn--gold:focus-visible,
.faq-v2__contact .btn.btn--gold:hover,
.faq-v2__contact .btn.btn--gold:focus-visible {
  background: rgba(139, 168, 65, 0.12);
  border-color: var(--green-medium, #3D6B1E) !important;
  color: var(--green-dark, #2D5016);
  box-shadow: none;
  filter: none;
}

/* ==========================================================================
   CLÚSTER I — Tokens off-spec en listado /es/campamentos (y su alias
   /es/campamentos/verano, que REDIRIGE a la misma página — verificado).
   IDs: P2-campamentos_verano-002, P2-campamentos_verano-003,
   P2-campamentos_verano-004, P2-campamentos-001, P3-campamentos-003.
   DOM verificado en dev: sí existen .E-camp-card__intl-badge (x5) y
   .E-camp-card__cta--intl (x5) — la nota de recon "no visibles" era sobre
   otra vista. Reglas a vencer: camp-filter.css (badges, plane, cta) y
   campamentos-mobile.css (cta--intl con !important).
   ========================================================================== */

/* CTA de conversión de card 'Ver fechas e inscribirse': verde plano -> dorado
   canónico .btn--gold (P2-campamentos_verano-004).
   !important: vence `.E-camp-card__cta { background:#2D5016 !important }` del
   campamentos-mobile.css DESPLEGADO en dev (drift vs repo, trazado en vivo). */
.E-camp-card__cta {
  background: linear-gradient(135deg, #C8A84E 0%, #E8D48A 100%) !important;
  color: var(--green-dark, #2D5016) !important; /* idem drift: color blanco legacy */
  box-shadow: 0 2px 10px rgba(200, 168, 78, 0.3);
}
.E-camp-card__cta:hover,
.E-camp-card__cta:focus-visible {
  background: linear-gradient(135deg, #C8A84E 0%, #E8D48A 100%) !important;
  color: var(--green-dark, #2D5016) !important;
  filter: brightness(1.05);
  box-shadow: 0 4px 16px rgba(200, 168, 78, 0.45);
}

/* CTA intl 'Solicitar info': azul prohibido -> outline verde (secundario,
   no es conversión directa). !important: vence background #3498DB !important
   de campamentos-mobile.css (archivo legacy intocable desde este lote). */
.E-camp-card__cta--intl,
.E-camp-card__cta.E-camp-card__cta--intl:hover,
.E-camp-card__cta.E-camp-card__cta--intl:focus-visible {
  background: transparent !important;
  border: 2px solid var(--green-brand, #8BA841);
  color: var(--green-dark, #2D5016);
  box-shadow: none;
  filter: none;
}
.E-camp-card__cta.E-camp-card__cta--intl:hover,
.E-camp-card__cta.E-camp-card__cta--intl:focus-visible {
  background: rgba(139, 168, 65, 0.12) !important; /* idem: vence hover #2980B9 !important */
  border-color: var(--green-medium, #3D6B1E);
}

/* Badge 'Internacional' azul -> verde oscuro de marca (blanco 9.4:1) */
.E-camp-card__intl-badge {
  background: rgba(45, 80, 22, 0.92);
}

/* Icono avión del filtro de ubicaciones: #3498DB -> verde medio */
.E-camp-filter__plane {
  color: var(--green-medium, #3D6B1E);
}

/* Badges de disponibilidad: verde Bootstrap ~#27AE60 -> verde medio de
   paleta (blanco 6.0:1); 'Lista de espera' naranja -> rojo urgencia #C0392B
   (P2-campamentos_verano-003, P3-campamentos-003) */
.E-camp-card__badge--available {
  background: rgba(61, 107, 30, 0.95);
}
.E-camp-card__badge--waitlist {
  background: rgba(192, 57, 43, 0.95);
}

/* ==========================================================================
   CLÚSTER G — CTA de conversión del popup 'Plazas limitadas' y FAB
   'Inscríbete': verde -> dorado canónico (conversión = .btn--gold).
   IDs: P2-home-001, P2-campamentos-002, P2-campamentos_toledo-003 (parte
   modal), P2-contacto-003, P2-colegios-003, P2-user_login-002.
   DOM verificado: el markup lo inyecta layoscamp_core/js/popup.js con
   style="background: #8BA841" INLINE en .lc-popup__cta (drupalSettings
   popupBgColor) -> el !important de background es para vencer ESE inline
   (JS de módulo, fuera del alcance CSS de este lote). Texto = #2D5016,
   igual que el 'Apúntate ya' del header (.btn--gold canónico).
   NOTA P2-user_login-002: la regla cubre popup y FAB en todas las páginas
   del theme frontend; /user/login renderiza con theme Gin (sin este CSS)
   -> en esa ruta concreta el fix es de config, ver nota CSS-vs-config.
   NOTA P2-user_login-006 (modal fantasma a 1024): NO REPRODUCIBLE con
   cookies cerradas -> no-fix-artifact, sin regla.
   ========================================================================== */
.lc-popup__cta {
  /* !important background: vence style="background:#8BA841" inline de popup.js.
     !important color: en la home reglas `a` por página (p.ej. path-frontpage)
     pisaban el color con #1A1A1A (trazado en vivo) — se iguala al header. */
  background: linear-gradient(135deg, #C8A84E 0%, #E8D48A 100%) !important;
  color: var(--green-dark, #2D5016) !important;
  box-shadow: 0 4px 14px rgba(200, 168, 78, 0.35);
}
.lc-popup__cta:hover,
.lc-popup__cta:focus-visible {
  color: var(--green-dark, #2D5016) !important;
  box-shadow: 0 6px 20px rgba(200, 168, 78, 0.45);
}
.lc-floating-cta {
  background: linear-gradient(135deg, #C8A84E 0%, #E8D48A 100%);
  color: var(--green-dark, #2D5016);
  box-shadow: 0 6px 20px rgba(200, 168, 78, 0.4), 0 2px 6px rgba(0, 0, 0, 0.1);
}
.lc-floating-cta:hover,
.lc-floating-cta:focus-visible {
  background: linear-gradient(135deg, #C8A84E 0%, #E8D48A 100%);
  filter: brightness(1.05);
  color: var(--green-dark, #2D5016);
  box-shadow: 0 8px 28px rgba(200, 168, 78, 0.55), 0 3px 8px rgba(0, 0, 0, 0.12);
}
.lc-floating-cta--visible::before {
  background: rgba(200, 168, 78, 0.3); /* pulso acorde al dorado */
}

/* ==========================================================================
   CLÚSTER F — Banner de consentimiento. Módulo real: CookiesJSR (NO
   eu-cookie-compliance). Theming legacy en style.css:12875+ con !important
   (botones 27px, fondo #31562d off-spec, texto 12px) — los !important de
   este bloque vencen ESOS !important vía mayor especificidad (#cookiesjsr).
   IDs: P2-campamentos_tarifa-006, P2-home-004, P2-campamentos_toledo-007,
   P2-campamentos_layoscamp-santander-...-006, P2-cart-006, P2-contacto-006,
   P2-equipo-005, P2-politica-de-cookies-003, P2-cart-002,
   P3-campamentos_sotogrande-009, P3-campamentos_kids-camp-008,
   P3-preguntas-frecuentes-008, P3-campamentos_curso-...-009.

   REQUISITOS LEGALES aplicados:
   - Simetría estricta Permitir <-> Denegar: los TRES botones (Configuración,
     Denegar todo, Permitir todo) comparten exactamente el mismo estilo
     (se neutraliza la variante .important del módulo que destacaba Permitir).
   - Tap target >= 44px los tres; en columna a 360 caben sin scroll
     (~370px < 640px de viewport útil).
   - Texto banner >= 14px blanco sobre #2D5016 (9.4:1 >= 4.5:1 AA).
   - Links a políticas visibles y SUBRAYADOS (AA), blanco 9.4:1.
   - Withdraw tab: N/A — CookiesJSR no tiene pestaña de retirada persistente;
     la reapertura va por link de footer (#modificarCookies, config
     openSettingsHash). No se oculta nada que el módulo ofrezca.

   NOTA CSS-vs-config: el banner usa los colores DEFAULT del módulo
   (drupalSettings sin theming) parcheados desde style.css legacy. Lo
   sostenible es definir las custom properties --banner-... y --btn-... del
   propio CookiesJSR (lib soporta vars) en la config del módulo o retirar
   el bloque legacy de style.css cuando se pueda tocar. Este bloque es el
   puente CSS hasta entonces.
   ========================================================================== */

/* Capa base del banner: V2 verde oscuro, Inter >= 14px blanco */
#cookiesjsr .cookiesjsr-banner {
  background-color: var(--green-dark, #2D5016) !important; /* vence #31562d !important de style.css */
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  color: #fff;
}
#cookiesjsr .cookiesjsr-banner .cookiesjsr-banner--info {
  font-size: 0.875rem !important; /* vence 12px !important de style.css */
  line-height: 1.5;
  color: #fff;
}

/* Links a políticas: visibles + subrayado AA (blanco 9.4:1 sobre #2D5016) */
#cookiesjsr .cookiesjsr-banner a,
#cookiesjsr .cookiesjsr-banner .cookiesjsr-links a {
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 2px;
}
#cookiesjsr .cookiesjsr-banner .cookiesjsr-banner--links {
  font-size: 0.875rem;
}

/* Botones: los TRES idénticos (simetría RGPD), >= 44px, pill blanco con
   texto verde oscuro (9.4:1). Se cubren .cookiesjsr-settings,
   [data-cookiesjsr="important.denyAll"] y [data-cookiesjsr="important.allowAll"]
   neutralizando la variante .important del módulo. */
#cookiesjsr .cookiesjsr-banner .cookiesjsr-btn,
#cookiesjsr .cookiesjsr-banner .cookiesjsr-btn.important,
#cookiesjsr .cookiesjsr-banner .cookiesjsr-btn.cookiesjsr-settings {
  min-height: 44px !important; /* vence min-height: initial !important de style.css */
  padding: 10px 18px;
  background-color: #fff !important; /* vence bg #31562d !important (settings) y default del lib */
  color: var(--green-dark, #2D5016) !important; /* vence color #31562d !important (.important) */
  border: 2px solid #fff;
  border-radius: 8px;
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-size: 0.875rem;
  font-weight: 600;
}
#cookiesjsr .cookiesjsr-banner .cookiesjsr-btn:hover,
#cookiesjsr .cookiesjsr-banner .cookiesjsr-btn:focus-visible {
  background-color: var(--green-bg, #F0F4E8) !important; /* vence hover white !important de style.css */
  color: var(--green-dark, #2D5016) !important;
  border-color: var(--green-bg, #F0F4E8);
}

/* Backdrop gris del bloque de cookies del theme (cookies-block.html.twig
   pinta <div class="overlay"> con rgba(0,0,0,.5) z-index 1031 vía style.css):
   oscurecía TODA la página hasta consentir (P2-cart-002) y quedaba por
   debajo de las cards sticky en fichas (P3-campamentos_curso-...-009).
   El banner CookiesJSR no necesita backdrop (no es modal bloqueante).
   :has() acota al overlay hermano de #cookiesjsr para no tocar otros usos.
   !important: el JS del theme muestra el overlay con style.display inline
   (verificado en vivo: la regla sin !important matcheaba y no aplicaba). */
.overlay:has(+ #cookiesjsr) {
  display: none !important;
}

/* ==========================================================================
   CLÚSTER D-P2 — Heros 'apagados': el gris era en parte artefacto del
   backdrop, pero el subtítulo/notas SÍ van en blanco translúcido 0.75/0.65
   (contraste justo sobre verde). Se sube la opacidad.
   IDs: P2-campamentos_curso-...-007, P2-campamentos_sotogrande-007,
   P3-conocenos-006 (H1 verificado YA blanco en vivo; el fix es el subtítulo).
   VEREDICTO no-fix-artifact (sin regla): P2-conocenos-001 (banda gris =
   backdrop del consent en captura stitched) y P2-colegios-004 (cards beige
   en 1440/2560 = mismo artefacto; en vivo #F0F4E8 correcto).
   ========================================================================== */
.page-hero__subtitle,
.camp-detail__subtitle {
  color: rgba(255, 255, 255, 0.92);
}
.camp-detail__price-note {
  color: rgba(255, 255, 255, 0.85); /* 'por turno de 7 dias' bajo el precio */
}

/* ==========================================================================
   CLÚSTER J-P2 — Formularios: patrón submit ÚNICO de marca (mata el verde
   oliva #6B8A2F, el pill blanco sin identidad y el dorado en 'Guardar').
   IDs: P2-contacto-005, P2-colegios-005, P2-user-006, P2-user-004,
   P3-colegios-006. P2-user_login-004: /user/login renderiza con theme GIN
   (body gin-login, verificado) -> este CSS no carga ahí; fix = config
   (theme negotiation / gin_login), ver nota CSS-vs-config en el report.
   DOM verificado: webforms frontend usan input.form-submit dentro de
   .form-actions; /user redirige a /es/panel (body .path-panel, theme
   frontend SÍ carga) con form.user-form y submit 'Guardar' en gradiente
   dorado por design-system-v2.css `body.path-panel .form-submit`.
   AA aplicada: fondo submit = var(--green) #3D6B1E (6.0:1 con texto blanco,
   AA OK); hover = var(--green-dark) #2D5016 (9.4:1, OSCURECE, no aclara).
   #8BA841 daba 2.6:1 (FALLA AA); #A4C256 hover daba aún menos. El #8BA841
   sigue siendo correcto en OTROS usos del lote (links/iconos/bordes sobre
   fondo claro) — aquí solo aplica a SUBMITS.
   ========================================================================== */
.webform-submission-form .form-actions .form-submit,
.path-panel .user-form .form-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 10px 28px;
  background: var(--green, #3D6B1E);
  color: #fff;
  border: none;
  border-radius: 50px;
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(61, 107, 30, 0.3);
  transition: background 0.2s ease, box-shadow 0.2s ease;
}
.webform-submission-form .form-actions .form-submit:hover,
.webform-submission-form .form-actions .form-submit:focus-visible,
.path-panel .user-form .form-submit:hover,
.path-panel .user-form .form-submit:focus-visible {
  /* hover = oscurecer hacia --green-dark (#2D5016, 9.4:1), no aclarar */
  background: var(--green-dark, #2D5016);
  color: #fff;
  box-shadow: 0 4px 14px rgba(45, 80, 22, 0.45);
}

/* 'Guardar' de /es/panel (P2-user-006): el design-system-v2.css DESPLEGADO
   en dev (drift vs repo, bloque checkout) dora con !important TODOS los
   `body.path-panel input.button.form-submit` — specificity 0,3,2 + !important,
   correcto en checkout (conversión=gold) pero se filtra al form de cuenta.
   El selector de abajo (body.path-panel form.user-form .form-actions
   input.form-submit) es 0,4,3 + !important → gana al drift sin tocarlo. */
body.path-panel form.user-form .form-actions input.form-submit {
  background: var(--green, #3D6B1E) !important;
  background-image: none !important;
  color: #fff !important;
  padding: 10px 28px !important;
  border-radius: 50px !important;
  box-shadow: 0 2px 8px rgba(61, 107, 30, 0.3) !important;
}
body.path-panel form.user-form .form-actions input.form-submit:hover,
body.path-panel form.user-form .form-actions input.form-submit:focus-visible {
  background: var(--green-dark, #2D5016) !important;
  background-image: none !important;
  color: #fff !important;
  box-shadow: 0 4px 14px rgba(45, 80, 22, 0.45) !important;
}

/* Contacto: el bloque de acciones flotaba solapándose con el primer
   checkbox RGPD en 768-1440 (P2-contacto-005) */
.page-node-type-contacto .webform-submission-form .form-actions {
  clear: both;
  float: none;
  width: 100%;
  margin-top: 24px;
}

/* Cuenta (/es/panel): formulario sin contenedor, campos de borde a borde
   (P2-user-004). max-width 720 centrado por directiva. */
.path-panel .user-form {
  max-width: 720px;
  margin-inline: auto;
  padding-inline: 16px;
}

/* Texto legal de checkboxes RGPD >= 13px en todos los webforms
   (P3-colegios-006; mismo umbral que el bloque P1 de contacto) */
.webform-submission-form .form-check label,
.webform-submission-form .js-form-type-checkbox .description {
  font-size: 0.8125rem;
  line-height: 1.5;
}

/* ==========================================================================
   CLÚSTER K — Jerarquía tipográfica.
   IDs: P2-cart-003 (H1 empty state en Inter -> Playfair). VEREDICTOS sin
   regla: P2-politica-de-cookies-002 = no-target-in-DOM (la página no
   renderiza headings dentro de .E-page-body__text, verificado);
   P2-user_login-003 (H1 login Playfair) = página theme Gin, este CSS no
   carga ahí -> config, ver nota CSS-vs-config.
   DOM verificado: h2.cart-empty__title (regla a vencer: style.css:24971
   Inter 700 #31562d, especificidad 0-1-0 — gana este archivo por orden).
   ========================================================================== */
.cart-empty__title {
  font-family: 'Playfair Display', Georgia, serif;
  color: var(--green-dark, #2D5016);
}


/* --------------------------------------------------------------------------
   P3 — Pulido
   -------------------------------------------------------------------------- */

/* ==========================================================================
   CLÚSTER L — Filtros, chips y controles táctiles.
   IDs: P2-campamentos_verano-007 (chips FECHAS cortados a 360: camp-filter.css
   fuerza nowrap + overflow-x auto con scrollbar oculto en <=767 — verificado
   computado flex-wrap:nowrap en vivo), P3-campamentos_verano-008 (pins
   multicolor visibles a 360 — verificado 6 iconos visibles),
   P2-preguntas-frecuentes-001 (lupa solapa placeholder: el padding-left:52px
   de design-system-v2-extras llega pisado a 10px computado — se reimpone con
   mayor especificidad), P2-user-008 (tabs de /es/panel a.nav-link < 44px).
   VEREDICTOS sin regla: P2-preguntas-frecuentes-006 = no-fix-artifact (en
   vivo los pills hacen wrap y el último termina en x=296 < 360, nada cortado);
   P2-user-002 = no-target-in-DOM (en /es/panel NO existe ningún h1/.page-title
   en el DOM a ningún ancho — restaurar el título es Twig, no CSS).
   JUSTIFICACIÓN max-width: las dos reglas @media (max-width) de abajo anulan
   overrides legacy definidos exactamente en ese rango (camp-filter.css <=767);
   la base mobile-first (wrap) ya existe en el propio camp-filter.css.
   ========================================================================== */
@media (max-width: 767.98px) {
  .E-camp-filter__chips {
    flex-wrap: wrap;
    overflow-x: visible;
  }
}
@media (max-width: 575.98px) {
  .E-camp-filter__loc-icon {
    display: none;
  }
}
.faq-v2 .faq-v2__search-input {
  padding-left: 52px; /* la lupa (left:20px + 24px) termina en 44px */
}
.path-panel .nav-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* ==========================================================================
   CLÚSTER M — Anchos de lectura y centrado de contenedores.
   IDs: P3-aviso-legal-004, P3-politica-de-privacidad-003 (cuerpo legal
   ~120-150 caracteres/línea en >=1440 -> cap a 75ch desde 1024; ambas
   páginas son node type pagina-textual con .page-content__body, verificado),
   P2-preguntas-frecuentes-002 (.faq-v2 .container con max-width:1200 pero
   margin-left:0 computado en vivo -> media página vacía en >=1440).
   P3-user_login-007 (login no escala en 2560) = theme Gin, sin alcance CSS
   desde el theme frontend -> config (nota CSS-vs-config).
   ========================================================================== */
@media (min-width: 1024px) {
  .page-node-type-pagina-textual .page-content__body {
    max-width: 75ch;
    margin-inline: auto;
  }
}
.faq-v2 .container {
  margin-inline: auto;
}

/* ==========================================================================
   CLÚSTER N — Equilibrio de columnas y estados vacíos.
   IDs: P3-campamentos_layoscamp-santander-...-007 (a 768 la grid 2fr/1fr
   deja la columna principal en ~510px y descompensada -> 1 columna en
   768-1023), P3-campamentos_tarifa-010 (>=1024: align-items:start para que
   la columna corta no estire su caja; el alto total sigue dictado por el
   contenido — equilibrio completo requiere contenido real, no CSS),
   P3-cart-007 (empty state anclado arriba con vacío debajo en >=1440:
   se encadena flex desde <main> — el body ya es d-flex flex-column h-100 —
   para que .cart-empty crezca y centre su contenido).
   VEREDICTO sin regla: P3-campamentos_toledo-009 = fixed-as-intended (la
   'franja blanca sobre el header' era scrollY=40 en la captura, no hay
   franja real en vivo).
   JUSTIFICACIÓN rango 768-1023: corrige una grid definida por extras solo
   con max-width 767; el rango expira en 1024 y no toca la base mobile.
   ========================================================================== */
@media (min-width: 768px) and (max-width: 1023.98px) {
  .camp-detail__info-grid {
    grid-template-columns: 1fr;
    gap: 32px;
  }
}
@media (min-width: 1024px) {
  .camp-detail__info-grid {
    align-items: start;
  }
}
.path-cart main {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}
.path-cart main .region-content,
.path-cart #block-frontend-content,
.path-cart #block-frontend-content > .content {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}
.path-cart .cart-empty {
  flex: 1 1 auto;
  justify-content: center;
}

/* ==========================================================================
   CLÚSTER O-P3 — Pulido visual restante.
   IDs: P3-noticias-006 (grid salta a 3 columnas ya en 768 — li con
   max-width:33.33% en flex wrap, verificado computado -> 2 columnas en
   tablet), P3-home-002 (carta fundadora: decisión Design Director =
   MANTENER itálica serif; en vivo .letter-body computa Inter italic por
   drift de fuentes -> se declara la serif explícita, NO pasar a Inter).
   VEREDICTOS sin regla: P3-home-001 = no-fix-artifact (en vivo .hero__bg
   computa cover y el kenBurns lo escala a 1571px > 1440px de hero: cubre
   todo el alto en 2560; el verde plano de la captura era el artefacto del
   stitch); P3-preguntas-frecuentes-007 = no-target-in-DOM (los
   .faq-v2__item computan box-shadow:none en vivo — no hay sombras grises
   que recolorear; la sombra del botón dorado era la canónica rgba dorada).
   JUSTIFICACIÓN rango 768-1023: anula un max-width legacy de style.css
   definido para todo ancho; expira en 1024 donde el 33.33% vuelve a ser
   correcto (3 columnas).
   ========================================================================== */
@media (min-width: 768px) and (max-width: 1023.98px) {
  .view-noticias .item-list ul li {
    max-width: 50%;
    flex-basis: 50%;
  }
}
.letter-body {
  font-family: 'Playfair Display', Georgia, serif;
  font-style: italic;
}

/* ==========================================================================
   CIERRE DE LOTE — IDs sin regla en este archivo (trazabilidad batch 2):
   - Cubiertos por el CLÚSTER A del batch 1 (header 769-1199):
     P2-campamentos_verano-005 (CTA cortado a 1024) y
     P3-campamentos_gredos-008 ('Curso de monitores' en 2 líneas: el
     white-space:nowrap del rango 992-1199 ya lo resuelve).
   - moved-to-twig (fuera de lote, refactor Twig): P2-campamentos_gredos-005
     y P2-campamentos_tarifa-007 (el vídeo YouTube no renderiza a 360:
     lazy/JS del embed, no es CSS).
   - Editorial (fuera de lote): P3-noticias-005 (capitalización inconsistente
     de titulares = contenido, no CSS).
   - no-change-by-design (Design Director): P3-campamentos-004 y
     P3-campamentos_verano-009 (títulos de camp-card en Inter 600 22px,
     correcto por decisión explícita — NO pasar a Playfair).
   - Theme Gin (sin alcance de este archivo; fix = config):
     P2-user_login-001..005/007 según aplique — detalle en el report.
   ========================================================================== */

