/* =====================================================================
   Indasa — sitio público

   Paleta tomada del sitio ACTUAL medida en vivo:
     - Verde de marca (fondos oscuros):  #083820
     - Verde de acción (botones/acento): #24de79
   Botones RECTANGULARES (el ACTUAL usa border-radius 0), no píldoras.
   Tipografía en la pila del sistema, sin CDN — la CSP del sitio es 'self'.
   ===================================================================== */

/* --- Tipografía del sitio ACTUAL: Kumbh Sans (variable 300–800) -------
   Auto-hospedada: la CSP del sitio es 'self', no admite CDN de fuentes. */
@font-face {
  font-family: 'Kumbh Sans';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url('/assets/fonts/kumbh-sans-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Kumbh Sans';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url('/assets/fonts/kumbh-sans-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* `<dialog>` nativo: el reset de arriba (`*{margin:0}`) es una regla de
   AUTOR, y en la cascada CSS el origen "autor" siempre gana sobre
   "user-agent" sin importar la especificidad — sin este `margin:auto`
   repetido acá, pisa el centrado nativo que el navegador aplica a
   `dialog:modal` (`showModal()`) y el diálogo queda pegado a la esquina
   superior-izquierda en vez de centrado (bug real, encontrado en
   Calculadora — code review 2026-09-22). Puesto UNA vez acá, junto al
   reset que lo causa, para que CUALQUIER `<dialog>` futuro en el sitio se
   centre solo sin que haga falta repetir este fix por cada uno. */
dialog:modal { margin: auto; }

:root {
  --accent: #24de79;       /* relleno de botones y acentos sobre oscuro */
  --accent-h: #1bc169;     /* hover */
  --accent-ink: #0a8f4f;   /* verde legible para texto/acentos sobre blanco */
  /* Verdes medidos del sitio ACTUAL (promedio real de cada franja). */
  --brand: #083820;        /* barra superior, footer, métricas */
  --hero-bg: #052213;      /* franja del título del hero (la más oscura) */
  --pasos-bg: #072c1a;     /* franja de los 6 pasos */
  --brand-2: #0c4a2b;

  --ink: #16211c;
  --ink-soft: #4b5563;
  --muted: #6b7280;
  --line: #e5e7eb;
  --surface: #fff;
  --page: #f5f7f5;

  --r: 4px;
  --btn-r: 2px;
  --container: 1180px;
  /* El ACTUAL estira el header, el carrusel y los 6 pasos a casi todo el ancho */
  --container-wide: 95.3%;
  --header-h: 89px;

  --font: 'Kumbh Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
          'Helvetica Neue', Arial, sans-serif;
}

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

body.body--site {
  font-family: var(--font);
  color: var(--ink);
  background: var(--surface);
  line-height: 1.5;
  overflow-x: hidden;
}

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: 24px;
}

/* Contenedor ancho: carrusel del hero y los 6 pasos, como en el ACTUAL */
.container-wide {
  width: var(--container-wide);
  max-width: 1860px;
  margin-inline: auto;
}
@media (max-width: 768px) { .container-wide { width: calc(100% - 40px); } }


/* --- Botones (rectangulares como el ACTUAL) -------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 13px 30px;
  border-radius: var(--btn-r);
  font-weight: 500;
  font-size: 14px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease, transform .1s ease;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
.btn__arrow { display: inline-block; font-weight: 400; }

/* Relleno verde de acción */
.btn--primary { background: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-h); }

/* Contorno blanco sobre fondo oscuro (header y hero) */
.btn--ghost-light { background: transparent; color: #fff; border-color: rgba(255,255,255,.7); }

/* Contorno + acento triangular verde en la esquina (Figma: botón "Calcula
   tu factura" del banner de Calculadora). El ACTUAL no lo renderiza. */
.btn--corner-accent {
  position: relative;
  overflow: hidden;
  padding-right: 46px;
}
.btn--corner-accent .btn__arrow { color: #fff; font-size: 1.4em; }
.btn--corner-accent:hover .btn__arrow { color: var(--brand); }
.btn--corner-accent::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 0 0 22px 22px;
  border-color: transparent transparent var(--accent) transparent;
}
.btn--ghost-light:hover { background: #fff; color: var(--brand); border-color: #fff; }

/* ---- Mecanismo compartido: triángulo que se expande con `clip-path`
   hasta cubrir todo el botón en `:hover` (ACTUAL: clase real
   "btn-expansion-esquina" de Servicios, leída de `document.styleSheets`
   — ver CLAUDE.md). 3 botones lo usan — `.sd-related__link` ("Otros
   servicios", Detalle de servicio), `.btn--solid-expand` (CTA de
   permisos, Servicios) y `.btn--outline-expand` (Contáctanos) — cada uno
   con su propio color/tamaño/tipografía; code review 2026-09-15: antes
   cada uno repetía el mecanismo completo (position/overflow/z-index/
   ::after/clip-path/transition) por separado, ya divergiendo en detalles
   menores (bottom+right+width+height vs inset:0, todos equivalentes). Se
   deja el color de `::after` en cada clase por separado a propósito:
   `.sd-related__link` usa `#61de82` (medido de ACTUAL, NO es
   `var(--accent)` aunque se parezca) — normalizarlo sería un cambio
   visual no pedido. */
.sd-related__link,
.btn--solid-expand,
.btn--outline-expand {
  position: relative;
  overflow: hidden;
  z-index: 1;
}
.sd-related__link::after,
.btn--solid-expand::after,
.btn--outline-expand::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  clip-path: polygon(100% 80%, 80% 100%, 100% 100%);
  transition: clip-path .5s ease-in-out;
}
.sd-related__link:hover::after,
.btn--solid-expand:hover::after,
.btn--outline-expand:hover::after { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }

/* Contorno blanco con el mecanismo de arriba — portado a pedido del
   usuario para los botones "Llamanos"/"Escríbenos a WhatsApp" de
   Contáctanos (`.cont-info`, fondo verde oscuro). A diferencia de
   `.sd-related__link` (fondo blanco, texto negro→blanco en hover) acá el
   texto ya es blanco desde el principio (fondo verde de marca detrás),
   así que no hace falta animar el color del texto — solo el triángulo y
   el borde. */
.btn--outline-expand {
  background: transparent;
  color: #fff;
  border-color: rgba(255, 255, 255, .7);
  transition: border-color .4s ease-in-out;
}
.btn--outline-expand::after { background-color: var(--accent); }
.btn--outline-expand:hover { border-color: var(--accent); }

/* Contorno de marca sobre fondo claro */
.btn--outline { background: transparent; color: var(--brand); border-color: var(--brand); }
.btn--outline:hover { background: var(--brand); color: #fff; }

.btn--lg { padding: 15px 34px; font-size: 15px; }

/* Revelado del ACTUAL (Avada `revealInLeft`, 0.6s, offset "top-into-view"):
   el botón está REALMENTE oculto (visibility:hidden) hasta que carga la
   página; en ese instante aparece ya cubierto por completo por una capa
   verde, que se desliza hacia la derecha revelando el botón debajo. No es
   un destello sobre un botón ya visible — medido en vivo en ACTUAL. */
.btn--reveal {
  position: relative;
  overflow: hidden;
  visibility: hidden;
  animation: btnRevealShow 0s .35s forwards;
}
@keyframes btnRevealShow { to { visibility: visible; } }
.btn--reveal::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent);
  transform: scaleX(1);
  transform-origin: right center;
  animation: revealInLeft .6s ease-in-out .35s both;
  pointer-events: none;
}
@keyframes revealInLeft {
  0%     { transform: scaleX(1); }
  100%   { transform: scaleX(0); }
}
.eyebrow {
  display: inline-block;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--accent-ink);
  margin-bottom: 12px;
}
.eyebrow--light { color: var(--accent); }

.section-title {
  font-size: clamp(24px, 3.2vw, 34px);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -.01em;
}

/* =====================================================================
   HEADER
   ===================================================================== */
.site-header {
  /* En el ACTUAL la barra es parte del flujo: se va con el scroll, sin
     sticky ni animación de ocultamiento. */
  position: static;
  background: var(--brand);
  min-height: var(--header-h);
  display: flex;
  align-items: center;
  overflow: visible;
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
.site-logo { display: inline-flex; align-items: center; }
.site-logo__img { height: 34px; width: auto; }
.site-logo__text { font-size: 22px; font-weight: 800; letter-spacing: -.02em; color: #fff; }

.nav-toggle {
  display: none; flex-direction: column; justify-content: center; gap: 5px;
  width: 42px; height: 42px; background: transparent; border: 0; cursor: pointer;
}
.nav-toggle span { display: block; height: 2px; background: #fff; border-radius: 2px; }

.site-nav { display: flex; align-items: center; gap: 22px; }
.site-nav__cta { display: flex; align-items: center; gap: 80px; }

/* En escritorio los enlaces van CENTRADOS en la barra y el CTA al
   extremo derecho (como el ACTUAL). `display: contents` saca al .site-nav
   del flujo para que <ul> y el CTA sean hijos directos del flex del
   header; en móvil vuelve a ser el panel desplegable. */
@media (min-width: 901px) {
  .site-nav { display: contents; }
  .site-nav ul { margin-inline: auto; }
  /* Separa el grupo del botón del borde derecho, como el ACTUAL, para
     que el botón no quede pegado al extremo. */
  .site-nav__cta { margin-right: 100px; }
}

/* Ícono de carrito del extremo derecho, con fadeInLeft como el ACTUAL */
.nav-cart {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; color: #fff; background: transparent;
  border: 0; cursor: pointer;
  animation: fadeInLeft 1s ease both;
}
.nav-cart svg { width: 22px; height: 22px; display: block; }
@keyframes fadeInLeft {
  from { opacity: 0; transform: translateX(-24px); }
  to   { opacity: 1; transform: translateX(0); }
}
.site-nav ul { display: flex; align-items: center; gap: 76px; list-style: none; }
/* Solo los enlaces del menú — no el botón CTA, que trae su propio padding
   y borde (si no, el borde inferior del botón se ve recortado). */
.site-nav ul a {
  font-size: 15px; font-weight: 400; color: #eef4f0;
  padding-block: 6px;
  transition: color .15s ease;
}
/* Solo color, sin subrayado (el ACTUAL no subraya el activo). */
.site-nav ul a:hover,
.site-nav ul a[aria-current="page"] { color: var(--accent); }

/* =====================================================================
   HERO — título arriba-izq, fila (botón izq · teléfono/correo der),
   y debajo la banda del slider (contenida en el container).
   ===================================================================== */
.hero { background: var(--hero-bg); color: #fff; }
/* Franja del carrusel: verde de marca sólido (#083820), como el ACTUAL;
   sin textura y sin alto extra — termina justo donde termina el carrusel. */
.hero__carousel { background: var(--brand); }
/* Fondo verde texturado real del ACTUAL (trae el patrón y el verde correcto) */
.hero__body { background: var(--hero-bg) url('/assets/img/hero-bg.jpg') center / cover no-repeat; padding-block: 46px 64px; }
/* En el ACTUAL el texto del hero es una columna en PORCENTAJE (arranca en
   ~21.8% y mide ~60% del viewport), no un ancho fijo: así conserva la
   misma proporción en cualquier resolución. */
/* Márgenes medidos del ACTUAL (izq 276→300, der 232→567 entre 1265 y
   1920). Así el borde derecho del bloque cae donde termina el teléfono,
   y `space-between` deja el teléfono justo al final del título. */
.hero__top {
  /* Estos márgenes crecen con el viewport hasta 1920px (valores medidos del
     ACTUAL). Por ENCIMA de 1920px se topan en su valor de 1920 (min(...,
     300/567px)) para no seguir creciendo con `vw`: de 1920px en adelante el
     escalado lo hace el zoom global (ver ultrawide-zoom.js), que
     ya multiplica todo el layout de 1920 — si `vw` siguiera creciendo aquí,
     el margen derecho se dispararía y aplastaría el bloque del título. */
  margin-left: min(calc(276px + (100vw - 1265px) * 0.0366), 300px);
  margin-right: min(calc(232px + (100vw - 1265px) * 0.5115), 567px);
  padding-inline: 0;
}
@media (max-width: 1100px) {
  .hero__top { margin-left: 0; margin-right: 0; padding-inline: 24px; }
}
.hero__title {
  /* Medido en el ACTUAL: el texto ocupa 357px a 1265 y 653px a 1920, o sea
     crece más rápido que el viewport. Esta interpolación pasa por ambos
     puntos (33px a 1280 y ~60px a 1920). El tope se fija en el valor de
     1920 (59.7px) — antes 62px, que solo se alcanzaba por encima de 1920,
     rango que ahora escala el zoom global (ver ultrawide-zoom.js). */
  font-size: clamp(24px, calc(33px + (100vw - 1280px) * 0.0417), 59.7px);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -.01em;
  /* fuerza el corte en 2 líneas: "Transforma Tu Empresa" / "Con Energía Limpia" */
  max-width: 11.2em;
  margin-bottom: 26px;
}
.hero__row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 18px 32px;
}
.hero__contact { display: flex; gap: 32px; flex-wrap: wrap; font-size: 14px; font-weight: 300; }
.hero__contact span { color: #fff; font-weight: 400; }

.hero__slider {
  position: relative;
  width: 100%;
  /* La forma de la PRIMERA imagen del carrusel (2026-09-30, pedido del
     usuario): site.js pone `--hero-proporcion` con sus medidas reales (ver
     home.php); sin dato, 1920/677, el tamaño de las fotos actuales. Así se ven
     completas: el ACTUAL usaba ALTO FIJO (400px) y la foto se recortaba según
     el ancho de pantalla (~40% perdido a 1920px). A cambio el carrusel crece
     en pantallas anchas (~480px a 1440, ~645px a 1920). En >1920px el zoom
     global (ver ultrawide-zoom.js) lo escala. */
  aspect-ratio: var(--hero-proporcion, 1920 / 677);
  overflow: hidden;
  border-radius: var(--r);
  background: var(--brand-2);
}
/* La entrante se desliza desde abajo hacia arriba (sobre la saliente);
   la saliente se va "para atrás": escala hacia el fondo y se desvanece.
   Duración: `--hero-transicion`, que pone site.js con el valor del panel
   (Inicio › Encabezado, «Duración de la transición»); 2 s si no llega. */
.hero__slide {
  position: absolute; inset: 0;
  opacity: 0;
  transform: translateY(100%);
  z-index: 1;
  transition: transform var(--hero-transicion, 2s) cubic-bezier(.4,0,.2,1), opacity var(--hero-transicion, 2s) ease-in-out;
}
.hero__slide.is-active { opacity: 1; transform: translateY(0); z-index: 3; }
.hero__slide.is-leaving { opacity: 0; transform: scale(.9); z-index: 2; }
.hero__slide.no-anim { transition: none; }
.hero__slide img { width: 100%; height: 100%; object-fit: cover; }

@media (max-width: 900px) {
  .hero__contact { gap: 6px 24px; }
}
/* En el celular se mantiene el alto fijo de siempre (se recortan un poco los
   costados): con la forma de la imagen quedaría de ~125px de alto. */
@media (max-width: 600px) {
  .hero__slider { aspect-ratio: auto; height: 230px; }
}

/* =====================================================================
   PROCESO (6 pasos) — sobre el verde oscuro que continúa del hero
   ===================================================================== */
/* `overflow: hidden` (2026-09-30): los pasos entran deslizándose desde el borde
   derecho (site.js, "6 pasos"); mientras se mueven quedaban más allá del borde
   y ensanchaban la página unos 4 s — en el celular eso dejaba achicar la
   página con zoom y moverla de costado (solo en Inicio, la única con esta
   animación). Recortar acá mantiene la animación sin tocar el ancho. */
.proceso { background: var(--pasos-bg) url('/assets/img/pasos-bg.png') center / cover no-repeat; color: #fff; padding-block: 90px 60px; overflow: hidden; }
.proceso__grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 34px 24px; }
.proceso__step { display: flex; flex-direction: column; }
.proceso__num { font-size: clamp(24px, 2.05vw, 32px); font-weight: 600; color: var(--accent); line-height: 1; margin-bottom: 20px; }
/* En el ACTUAL los pasos son imágenes, así que su texto ESCALA con el
   ancho de la columna. Se usa vw para que crezca igual en pantallas
   grandes y para que los cortes de línea no cambien con la resolución. */
/* `min(…vw, …px)`: hasta 1920px el texto escala con el ancho de columna (vw,
   como el ACTUAL); a partir de 1920px se topa en su valor de 1920 (23.2px /
   20.3px) para que no siga creciendo con `vw` y lo escale el zoom global (ver
   ultrawide-zoom.js) — de lo contrario se duplicaría el escalado en anchas. */
.proceso__step h3 { font-size: min(1.21vw, 23.2px); font-weight: 300; color: #fff; line-height: 1.4; margin-bottom: 12px; }
.proceso__step p { font-size: min(1.055vw, 20.3px); font-weight: 300; line-height: 1.6; color: #a9c4b5; margin-bottom: 22px; }
@media (max-width: 1024px) {
  .proceso__step h3 { font-size: 17px; }
  .proceso__step p { font-size: 14px; }
}
.proceso__step::after { content: ""; margin-top: auto; height: 7px; background: #8d9d94; }
@media (max-width: 1024px) { .proceso__grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 640px) { .proceso__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 400px) { .proceso__grid { grid-template-columns: 1fr; } }

/* =====================================================================
   PREMIO — título full-width + 3 columnas (texto+1ºLugar | foto | marcas)
   Fondo blanco, como el ACTUAL.
   ===================================================================== */
.premio { background: #fff; padding-block: 72px; }
.premio__inner { width: 100%; max-width: 1340px; margin-inline: auto; padding-inline: 24px; }

.premio__titulo {
  font-size: clamp(24px, 2vw, 38px);
  font-weight: 700;
  line-height: 1.25;
  color: #001f0b;                 /* verde muy oscuro, medido del ACTUAL */
  max-width: 15.4em;              /* en em: el corte (L3="y ER en El Salvador") se mantiene en toda resolución */
  margin-bottom: 16px;
}
.premio__head { position: relative; margin-bottom: 40px; }
.premio__head::after {            /* línea gris corta bajo el título */
  content: ""; display: block; width: 185px; height: 6px;
  background: #d9dedb; border-radius: 3px;
}

.premio__grid {
  display: grid;
  grid-template-columns: 1.45fr 1fr 1fr;
  gap: 64px;
  align-items: start;
}
.premio__desc { color: #555; font-size: clamp(17px, 1.5vw, 26px); line-height: 1.45; margin-bottom: 36px; }
.premio__lugar {
  display: block;
  font-size: clamp(56px, 5.6vw, 96px);
  font-weight: 600;               /* menos grueso que antes */
  line-height: 1;
  color: var(--accent);           /* #24DE79 */
  letter-spacing: -.01em;
}
.premio__col--foto img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--r); aspect-ratio: 600/660; }

/* Panel gris del mismo tamaño que la foto, con los 4 logos en 2×2. */
.premio__col--marcas {
  background: #f6f6f6;
  border-radius: var(--r);
  aspect-ratio: 600/660;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8% 6%;
  place-content: center;
  justify-items: center;
  padding: 6%;
}
.premio__marca { display: flex; align-items: center; justify-content: center; width: 100%; }
.premio__marca img { max-width: 100%; max-height: 90px; width: auto; object-fit: contain; }

@media (max-width: 900px) {
  .premio__grid { grid-template-columns: 1fr; gap: 40px; }
  .premio__titulo { max-width: none; }
  .premio__desc { margin-bottom: 20px; }
}

/* =====================================================================
   MARQUEE (revertido a texto en movimiento 2026-09-16, a pedido del
   usuario — el banner estático de la ronda 2026-09-15 se mantiene en
   Nosotros, `.nos-quote`, pero Inicio vuelve a esta versión)
   ===================================================================== */
.marquee { background: var(--brand); color: #fff; overflow: hidden; padding-block: 22px; white-space: nowrap; }
.marquee__track { display: inline-flex; gap: 48px; animation: marquee 28s linear infinite; will-change: transform; }
.marquee__item { display: inline-flex; align-items: center; gap: 16px; font-size: 20px; font-weight: 800; }
.marquee__item em { font-style: normal; font-weight: 400; font-size: 14px; color: #b9e8cf; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* =====================================================================
   SERVICIOS — tarjetas altas con el título SOBRE la imagen
   ===================================================================== */
.servicios { padding-block: 72px; }
/* Mismo ancho que la sección Premio */
.servicios__inner { width: 100%; max-width: 1340px; margin-inline: auto; padding-inline: 24px; }

/* Encabezado: título+subtítulo a la izquierda, botón a la derecha */
.servicios__head {
  display: flex;
  align-items: flex-end;          /* el botón queda a la altura del subtítulo */
  justify-content: flex-start;    /* botón cerca del texto, no pegado al borde */
  gap: 44px;
  margin-bottom: 40px;
}
.servicios__titulo { font-size: clamp(30px, 2.5vw, 48px); font-weight: 700; line-height: 1.05; color: #001f0b; }
.servicios__sub {
  font-size: clamp(24px, 2vw, 38px);
  font-weight: 300;
  line-height: 1.2;
  color: #001f0b;
  margin-top: 10px;
  max-width: 17em;                /* corte en 2 líneas, estable por em */
}
.servicios__cta { flex-shrink: 0; margin-bottom: 4px; }

.servicios__cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
@media (max-width: 860px) {
  .servicios__head { flex-direction: column; align-items: flex-start; gap: 20px; }
}

.servicio-card {
  position: relative;
  aspect-ratio: 7 / 10;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--brand-2);
  display: flex;
  align-items: flex-end;
}
.servicio-card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.servicio-card::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(8,56,32,0) 35%, rgba(8,56,32,.85) 100%);
}
.servicio-card__body { position: relative; z-index: 1; padding: 22px; color: #fff; }
.servicio-card__body h3 { font-size: 18px; font-weight: 800; line-height: 1.2; }
.servicio-card__body p { font-size: 13px; color: #d8ece0; margin-top: 6px; }
.servicio-card__body::after { content: ""; display: block; width: 46px; height: 4px; background: var(--accent); border-radius: 2px; margin-top: 14px; }
@media (max-width: 1024px) { .servicios__cards { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .servicios__cards { grid-template-columns: 1fr; } .servicio-card { aspect-ratio: 3/2; } }

/* =====================================================================
   METRICAS
   ===================================================================== */
.metricas { background: var(--surface); padding-block: 56px; }
.metricas__grid { display: grid; grid-template-columns: repeat(4, 1fr); text-align: center; gap: 32px 24px; }
.metrica { display: flex; flex-direction: column; align-items: center; }
.metrica__valor { display: block; margin-top: 22px; margin-bottom: 8px; font-size: clamp(44px, 4.6vw, 62px); font-weight: 600; color: #083820; line-height: 1; }
.metrica__etiqueta { display: block; font-size: clamp(15px, 1.1vw, 18px); color: var(--muted); }

/* El número y la descripción permanecen fijos siempre (solo la tarjeta
   entera hace fade-in como el resto de secciones, vía .reveal genérico).
   El ÍCONO es lo único que se mueve: flota de izquierda a derecha y
   viceversa, en bucle infinito, igual que el ACTUAL. */
.metrica__icon {
  display: block;
  color: var(--accent);
  animation: metrica-icon-float 3.6s ease-in-out infinite;
}
.metrica__icon svg { width: 76px; height: 76px; display: block; }

@keyframes metrica-icon-float {
  0%, 100% { transform: translateX(-10px); }
  50% { transform: translateX(10px); }
}

@media (max-width: 768px) { .metricas__grid { grid-template-columns: repeat(2, 1fr); gap: 36px 24px; } }

/* =====================================================================
   CALCULADORA (banner de dos mitades)
   ===================================================================== */
.calc-banner { padding-block: 64px; }
.calc-banner__grid {
  display: grid; grid-template-columns: 1fr 1fr;
  border-radius: var(--r); overflow: hidden;
}
.calc-banner__media { background: var(--brand-2); min-height: 340px; }
.calc-banner__media img { width: 100%; height: 100%; object-fit: cover; }
.calc-banner__body { background: var(--brand); color: #fff; padding: 48px; display: flex; flex-direction: column; justify-content: center; }
.calc-banner__body .eyebrow { text-transform: none; font-weight: 400; letter-spacing: normal; }
.calc-banner__body h2 { font-size: clamp(22px, 3vw, 30px); font-weight: 500; margin-bottom: 14px; line-height: 1.25; max-width: 10em; }
.calc-banner__body p { color: #cfe4d8; margin-bottom: 24px; max-width: 27em; }
.calc-banner__body .btn { align-self: flex-start; }
@media (max-width: 768px) {
  .calc-banner__grid { grid-template-columns: 1fr; }
  .calc-banner__media { min-height: 240px; }
  .calc-banner__body { padding: 32px 24px; }
}

/* =====================================================================
   CLIENTES — franja de logos
   ===================================================================== */
.clientes { padding-block: 64px 108px; text-align: center; }
.clientes h2 { margin-bottom: 36px; }

/* Antes: grilla fija de 8, cada logo con una altura escrita a mano por
   posición (nth-child 1..8, medida del sprite viejo) — no hay forma de
   escribir esa regla para un logo que todavía no existe. Ahora es una
   franja que se desliza sola (misma técnica que .marquee/.marquee__track
   más arriba) y cada imagen conserva su alto/ancho natural dentro de una
   caja máxima — mismo espíritu que antes ("no una altura uniforme
   forzada"), pero sin depender de cuántos logos haya. */
.clientes__viewport { overflow: hidden; white-space: nowrap; }
.clientes__track {
  /* `inline-flex`, NO `flex`: uno de bloque se estira al ancho del
     contenedor (acá, el `.container` de la sección) y ahí se queda —
     el `translateX(-50%)` de la animación es un porcentaje DE ESE
     ANCHO PROPIO, así que con `flex` terminaba moviéndose la mitad del
     ancho de la tarjeta, no la mitad del contenido real (mucho más
     ancho, con 4 copias de todos los logos) — de ahí el salto/reinicio
     feo que se veía. `inline-flex` (igual que .marquee__track, que
     nunca tuvo este problema) hace que la caja se achique/agrande al
     ancho real de sus hijos, así el -50% cae justo donde tiene que
     caer: a mitad de las 4 copias, sin importar cuántos logos haya. */
  display: inline-flex; flex-wrap: nowrap; align-items: center;
  gap: 38px;
  animation-name: clientes-scroll;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  will-change: transform;
}
.clientes__logo { display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.clientes__logo img { height: auto; width: auto; max-height: 90px; max-width: 170px; object-fit: contain; display: block; }

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

/* Duración por escalón según cuántos logos haya (home.php elige la
   clase): el recorrido se ve igual de lento sea cual sea la cantidad,
   en vez de acelerarse con más logos. NO se calcula en línea con
   `style="animation-duration:…"` porque el CSP del sitio es
   `style-src 'self'` (sin 'unsafe-inline') y lo ignora en silencio. */
.clientes__track--t1 { animation-duration: 28s; }
.clientes__track--t2 { animation-duration: 40s; }
.clientes__track--t3 { animation-duration: 52s; }
.clientes__track--t4 { animation-duration: 64s; }
.clientes__track--t5 { animation-duration: 76s; }

@media (max-width: 900px) { .clientes__track { gap: 30px; } }
@media (max-width: 480px) {
  .clientes__track { gap: 22px; }
  .clientes__logo img { max-height: 55px; max-width: 105px; }
}

/* =====================================================================
   FOOTER — achicado 2026-09-16 a pedido del usuario, para que el alto
   total ronde el del hero compacto (300px, el mismo min-height que
   Nosotros/Servicios/Detalle/Contáctanos) en vez de los ~752px que medía
   antes @1920. Misma información que siempre (logo+claim+redes, las 3
   columnas de contacto, el formulario y el copyright), reagrupada en 3
   columnas (segundo pedido del usuario, mismo día): marca | teléfonos+
   correo (angosta) | oficinas+formulario — antes eran 5 columnas sueltas
   en una sola fila. Tipografía/spacing bajados a un tamaño compacto propio
   (ya no hay un ACTUAL más chico del cual medir esto — es diseño nuevo, no
   réplica). El fondo (`footer-bg.png`), los íconos de red reales y el
   botón cuadrado verde se conservan igual que siempre.
   ===================================================================== */
.site-footer {
  position: relative;
  background: var(--brand) url('/assets/img/footer-bg.png') center / cover no-repeat;
  color: #fff;
  padding-block: 64px 40px;
}

/* Columnas por CONTENIDO, no por fracción del contenedor (corregido
   2026-09-16, segunda vuelta): un primer intento repartía el ancho
   sobrante en fracciones `fr` (1.54fr/.41fr/1.6fr) — como cada columna
   real (marca ~494px, teléfonos/correo ~180px, oficinas+form ~501px @1920)
   es bastante más angosta que la fracción que le tocaba, quedaban 2
   bolsones de aire en blanco DENTRO de las columnas (marca y oficinas+
   form), justo donde el usuario los marcó con rectángulos rojos en una
   captura. `max-content` ancla cada columna a su propio contenido — el
   espacio sobrante ya no queda escondido a mitad de columna. **Segunda
   vuelta (mismo día, pedido del usuario con captura)**: ese sobrante,
   dejado como margen al final de la fila (`justify-content` por defecto),
   se veía como un bloque enorme de nada a la derecha — se agregó
   `justify-content:center` para repartirlo como margen simétrico a los 2
   lados en vez de todo de un lado, y se agrandó el contenido de la
   columna de marca (logo/claim/redes, ver abajo) para que ocupe más de
   ese espacio en vez de solo desplazarlo. */
.site-footer__row {
  position: relative; z-index: 1;
  display: grid;
  /* minmax(28ch, …) en la columna angosta: por debajo de ~1400px el texto
     de "Teléfonos" ya está en el piso de su clamp (12px, no encoge más) y
     necesita ~156px reales / ~22.5ch ("Whatsapp: (+503) 7890 0987", medido
     con canvas.measureText Y con un elemento de prueba a `width:100ch` para
     sacar el valor real de 1ch en esta fuente — 6.95px a 12px, no un
     redondeo de cabeza) — sin el piso, se encoge por debajo de eso y el
     número se parte en 2 líneas. Corregido en code review (2026-09-16): un
     piso en PX fijo (antes 165px, calibrado al pixel exacto del string de
     HOY) se rompe apenas el admin cargue un teléfono/whatsapp más largo
     desde el panel (`telefono`/`whatsapp` son contenido editable del CMS,
     no texto fijo de diseño). `ch` escala con el tamaño de fuente como un
     `em`, y 28ch (≈194px a 12px) deja ~25% de margen real sobre el string
     más largo medido, para absorber un valor más largo sin tener que
     volver a tocar este número.

     La 3ª columna es `minmax(0, max-content)`, NO `max-content` a secas
     (arreglo del desborde horizontal de PÁGINA entre ~1000 y ~1300px: 23px
     a 1280, 151px a 1024, en TODAS las páginas por el footer). `max-content`
     a secas tiene piso = su contenido más ancho (la fila "input + botón" del
     formulario de Oficinas), así que cuando la suma de las 3 columnas + los
     2 gaps ya no entra, esa columna se negaba a achicarse y empujaba el
     footer fuera de la ventana. Con piso 0 sigue midiendo su contenido
     cuando hay lugar (mismo resultado que antes en pantallas grandes) y
     cede lo que haga falta cuando no. Este arreglo ya se había hecho y
     verificado en vivo (PR#13) y se perdió del código sin que nadie lo
     notara (2026-09-23) — no volver a `max-content`. */
  grid-template-columns: max-content minmax(28ch, max-content) minmax(0, max-content);
  justify-content: center;
  gap: 64px;
  align-items: start;
}

/* Teléfonos+Correo (angosta) y Oficinas+Formulario: cada una es UN ítem
   de grid con sus 2 bloques apilados adentro — así la altura de cada
   columna la da la suma de sus 2 bloques + el gap interno, no un tercer
   nivel de columnas. */
.site-footer__group { display: flex; flex-direction: column; gap: 24px; min-width: 0; }

.site-footer__brand { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
/* Agrandados (pedido del usuario, misma ronda que `justify-content:center`
   de arriba): la columna de marca es la que más se beneficia de un
   contenido más grande porque es la única con margen de sobra real (el
   claim es una sola línea corta en vez de envolver a 2-3). */
.site-footer__logo { height: 56px; width: auto; margin-bottom: 22px; }
.site-footer__claim { color: #fff; font-size: clamp(18px, 1.3vw, 26px); font-weight: 700; line-height: 1.35; margin-bottom: 26px; }

.site-footer__social { display: flex; gap: 18px; list-style: none; }
.site-footer__social img { display: block; width: 36px; height: 36px; }

.site-footer__contact-col h3 { font-size: clamp(12.5px, .82vw, 15.5px); font-weight: 700; color: #fff; margin-bottom: 10px; }
.site-footer__contact-col p { font-size: clamp(12px, .72vw, 14px); color: #939494; line-height: 1.55; margin-bottom: 5px; }
.site-footer__contact-col p:last-child { margin-bottom: 0; }

.site-footer__form h2 { font-size: clamp(12.5px, .82vw, 15.5px); font-weight: 500; margin-bottom: 16px; line-height: 1.35; }
.site-footer__form-row { display: flex; align-items: flex-end; gap: 12px; }
/* El input se achica para que el borde derecho del botón "Enviar" quede
   alineado con el borde derecho de la dirección ("...San Salvador, El
   Salvador.") de la columna "Nuestras Oficinas" de arriba (pedido del
   usuario). Un primer intento aproximó esto con una fórmula `vw` fija,
   calibrada en 2 anchos — quedaba exacta SOLO en esos 2 puntos y desviaba
   ±25px en anchos intermedios, porque el ancho real del texto de la
   dirección no crece de forma lineal con el viewport. El `max-width` real
   se mide en vivo y se fija por JS (`site.js`, "Footer: alinear 'Enviar'
   con el borde derecho de la dirección") en cada carga/resize — el 60%
   de acá es solo el valor de arranque antes de que el JS corra (evita un
   salto grande) y el respaldo sin JavaScript. */
.site-footer__form-row input {
  flex: 1; min-width: 0; max-width: 60%;
  padding: 9px 0; border-radius: 0;
  border: none; border-bottom: 1px solid #9ea0a4; background: transparent;
  color: #9ea0a4; font-size: 13.5px; font-family: var(--font);
}
.site-footer__form-row input::placeholder { color: rgba(158,160,164,.6); }

/* Botón "Enviar": mismo estilo cuadrado/plano de siempre, achicado. */
.site-footer__submit {
  flex-shrink: 0;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 11px 18px;
  background: var(--accent); color: #fff; border: none; border-radius: 0;
  font-family: var(--font); font-size: 13.5px; font-weight: 700;
  cursor: pointer; transition: background .15s ease;
}
.site-footer__submit:hover { background: var(--accent-h); }
.site-footer__submit .btn__arrow { font-weight: 400; }

.site-footer__bottom { margin-top: 44px; font-size: 13px; color: #888e8a; text-align: center; }

@media (max-width: 900px) {
  .site-footer__row { grid-template-columns: 1fr 1fr; row-gap: 32px; }
  .site-footer__group:last-child { grid-column: 1 / -1; }
}
@media (max-width: 620px) {
  .site-footer__row { grid-template-columns: 1fr; }
  .site-footer__form-row { flex-direction: column; align-items: stretch; }
  /* Apilado (input arriba, botón abajo, ambos a lo ancho): la alineación
     con la dirección ya no aplica (no están uno al lado del otro) — el
     input vuelve a ocupar todo el ancho, igual que el botón. El JS de
     `alignFooterForm()` (site.js) también detecta este modo y no fuerza
     ningún max-width acá. */
  .site-footer__form-row input { max-width: none; }
}

/* =====================================================================
   ANIMACIONES — fade-in al entrar en viewport
   ===================================================================== */
.reveal { opacity: 0; transform: translateY(24px); transition: opacity .7s ease, transform .7s ease; }
.reveal.is-visible { opacity: 1; transform: none; }
/* Mientras no se ve, no se puede tocar (2026-09-28): el bloque ya está en su
   lugar pero invisible hasta que entra en pantalla (≈140 px sobre el borde de
   abajo), y en esa franja un toque caía en sus enlaces — p. ej. el botón
   "Contáctanos" de "Gestión de permisos" en /servicios llevaba a Contáctanos
   sin que se viera nada. Con el teclado sigue igual: enfocar un enlace lleva
   el bloque a la vista y se revela. */
.reveal:not(.is-visible) { pointer-events: none; }

/* Los 6 pasos entran desde el extremo derecho de la página deslizándose
   a la izquierda (slideInRight), escalonados. La animación la maneja el
   JS con la Web Animations API (no sujeta a la CSP `style-src`), que
   calcula por paso la distancia real al borde derecho de la página.
   Aquí solo se ocultan hasta que animen. */
.step-anim { opacity: 0; }
.step-anim.is-shown { opacity: 1; }

/* =====================================================================
   BOTÓN "IR ARRIBA" — como el ACTUAL: fijo abajo-derecha, fondo #333,
   esquinas superiores redondeadas; aparece al bajar.
   ===================================================================== */
.to-top {
  position: fixed;
  right: 75px;
  bottom: 0;
  z-index: 9999;
  width: 48px;
  height: 35px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #333;
  color: #fff;
  border-radius: 6px 6px 0 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity .25s ease, transform .25s ease, visibility .25s, background .15s ease;
}
.to-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
.to-top:hover { background: #65bc7b; }
.to-top svg { width: 22px; height: 22px; display: block; }
@media (max-width: 640px) { .to-top { right: 20px; } }

/* =====================================================================
   NAV RESPONSIVE (mobile)
   ===================================================================== */
@media (max-width: 900px) {
  .nav-toggle { display: flex; }
  .site-nav {
    position: fixed; inset: var(--header-h) 0 0 0; background: var(--brand);
    flex-direction: column; align-items: flex-start; padding: 24px; gap: 24px;
    transform: translateY(-8px); opacity: 0; visibility: hidden;
    transition: opacity .2s ease, transform .2s ease, visibility .2s;
    /* Blindaje: por encima de cualquier contenido de la página (carrusel,
       secciones con su propio stacking context), para que el panel tape
       todo lo que hay debajo mientras está abierto. */
    z-index: 1000;
    overflow-y: auto;
  }
  .site-nav.is-open { opacity: 1; transform: translateY(0); visibility: visible; }
  .site-nav ul { flex-direction: column; align-items: flex-start; gap: 18px; }
  .site-nav .btn { width: 100%; justify-content: center; }
}

/* =====================================================================
   NOSOTROS — hero, quiénes somos, distribuidor, misión/visión,
   cita, galería. Medido en vivo del ACTUAL (indasasv.com/nosotros).
   ===================================================================== */

/* ---- HERO ---- */
.nos-hero {
  position: relative;
  isolation: isolate;
  background: var(--brand);
  overflow: hidden;
  min-height: 300px;
  /* padding-top 70px (2026-09-13, pedido del usuario): mismo nivel que el
     título de Servicios ("Nuestros Servicios"), para que el título/línea/
     descripción de las 3 páginas con hero (Nosotros/Servicios/Detalle)
     arranquen a la misma altura — antes 50px, valor propio sin relación con
     las otras dos. El alto total (300px, min-height, sin cambios) es ahora
     la referencia que igualan Servicios y Detalle (ver `.serv-hero`/
     `.sd-hero` abajo). */
  padding: 70px 0 56px;
}
.nos-hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  z-index: -1;
}
/* Rediseño 2026-09-13, corregido el mismo día (aclaración del usuario): NO
   es "alinear con la siguiente sección" — es una copia EXACTA (posición,
   tamaño de letra, espaciado) del hero de Servicios. Misma estructura que
   `.serv-hero__inner` (`.container-wide` por fuera + `margin-left:12%` +
   `max-width:640px` por dentro) para que el resultado en px sea idéntico en
   cualquier resolución — ver `.uw-wide .nos-hero__inner` más abajo para el
   mismo override de ultra-wide que usa `.serv-hero__inner`. */
.nos-hero__inner { margin-left: 12%; max-width: 640px; color: #fff; }

/* ---- Título/línea/subtítulo del hero — COMPARTIDO por las 4 páginas con
   hero (Nosotros/Servicios/Detalle/Contáctanos), un solo selector agrupado
   en vez de 4 copias casi idénticas (code review 2026-09-15: las 4 copias
   ya habían empezado a divergir por accidente — `.sd-hero__subtitle` tenía
   `rgba(255,255,255,.78)` en vez de `.82` como las otras 3, y el margen de
   la línea estaba escrito de 2 formas equivalentes pero distintas; se
   normalizó a un solo valor de cada uno al fusionar). El `max-width:640px`
   que tenían `.nos-hero__subtitle`/`.sd-hero__subtitle` se quitó por
   redundante: el contenedor padre (`.X-hero__inner`, arriba) ya limita a
   640px en las 4 páginas. Cualquier ajuste futuro de tamaño/color/espaciado
   del hero se hace UNA vez acá, no en 4 sitios del archivo. */
.nos-hero__title,
.serv-hero__title,
.sd-hero__title,
.cont-hero__title,
.calc-hero__title,
.shop-hero__title {
  font-size: clamp(28px, 2.6vw, 42px);
  font-weight: 700;
  line-height: 1.2;
  color: #fff;
}
.nos-hero__sep,
.serv-hero__sep,
.sd-hero__sep,
.cont-hero__sep,
.calc-hero__sep,
.shop-hero__sep,
.nos-quote__sep {
  display: block;
  width: 110px;
  height: 4px;
  background: var(--accent);
}
.nos-hero__sep,
.serv-hero__sep,
.sd-hero__sep,
.cont-hero__sep,
.calc-hero__sep,
.shop-hero__sep { margin-top: 20px; }
.nos-quote__sep { margin: 22px auto 0; }
.nos-hero__subtitle,
.serv-hero__subtitle,
.sd-hero__subtitle,
.cont-hero__subtitle,
.calc-hero__subtitle,
.shop-hero__subtitle {
  margin-top: 16px;
  font-size: clamp(14px, 1vw, 16px);
  font-weight: 400;
  color: rgba(255, 255, 255, .82);
}
/* Entrada suave (2026-09-14, pedido del usuario): mismo stagger en las 5
   páginas (Calculadora sumada 2026-09-22, mismo criterio exacto). */
.nos-hero__sep.reveal-in,
.serv-hero__sep.reveal-in,
.sd-hero__sep.reveal-in,
.cont-hero__sep.reveal-in,
.calc-hero__sep.reveal-in,
.shop-hero__sep.reveal-in { animation-delay: .1s; }
.nos-hero__subtitle.reveal-in,
.serv-hero__subtitle.reveal-in,
.sd-hero__subtitle.reveal-in,
.cont-hero__subtitle.reveal-in,
.calc-hero__subtitle.reveal-in,
.shop-hero__subtitle.reveal-in { animation-delay: .2s; }

/* ---- FONDO BLANCO LISO (intro + distribuidor) ---- */
.nos-blanco { background: #fff; }

/* ---- QUIÉNES SOMOS (intro) ---- */
.nos-intro { padding: 68px 0 40px; }
/* Ancho para que cada línea forzada (br.brk) del párrafo quepa completa
   y reproduzca la misma distribución del ACTUAL (Kumbh Sans es algo más
   ancho que la fuente-imagen del ACTUAL, por eso ~660 y no 600). */
/* Centrado horizontalmente (a pedido del usuario 2026-09-12; antes iba
   indentado 12% a la izquierda como el ACTUAL). El texto interno sigue
   alineado a la izquierda; lo que se centra es la posición del bloque, para
   que Nosotros quede coherente con Misión/Visión y la galería (ya centrados).

   IMPORTANTE (corregido 2026-09-13): `.nos-intro__block` es ahora el bloque
   de ALINEACIÓN (mismo max-width que `.nos-distrib__grid`, 1130px, para que
   al centrarse ambos por separado terminen compartiendo el mismo borde
   izquierdo — antes tenían max-width distinto —722 vs 1130— y cada uno se
   centraba a su propio ancho, dejando un salto de ~204px entre "Quiénes
   somos" y "Distribuidor autorizado" pedido por el usuario que se corrigiera).
   El ancho real de AJUSTE DE TEXTO (722px, calibrado para los saltos `.brk`)
   vive ahora en `.nos-intro__inner`, un wrapper nuevo dentro del bloque. */
.nos-intro__block { max-width: 1130px; margin-inline: auto; }
.nos-intro__inner { max-width: 722px; }
.nos-intro__eyebrow {
  display: block;
  font-size: clamp(30px, 3.1vw, 40px);
  font-weight: 700;
  line-height: 1.05;
  color: var(--brand);
}
.nos-intro__title {
  margin-top: 14px;
  font-size: clamp(27px, 2.7vw, 36px);
  font-weight: 300;
  line-height: 1.1;
  color: var(--brand);
  letter-spacing: -.01em;
}
.nos-intro__text {
  margin-top: 32px;
  font-size: clamp(16px, 1.25vw, 18px);
  font-weight: 400;
  line-height: 1.5;
  color: #7a7a7a;
}
/* Línea gris horizontal bajo el párrafo (como el ACTUAL). */
.nos-intro__sep {
  display: block;
  width: 185px;
  height: 4px;
  background: #d8dcda;
  margin-top: 44px;
}

/* ---- DISTRIBUIDOR AUTORIZADO ---- */
.nos-distrib { padding: 24px 0 64px; }
/* Centrado, en línea con el bloque "Quiénes somos" (ambos centrados a pedido
   del usuario; antes iban indentados 12% dentro de .container-wide). */
/* Solo el texto (título, "+N", etiqueta). Hasta el 2026-09-29 era una grilla
   de 3 columnas: el texto, 4 logos fijos y el sello "Distribuidor autorizado";
   ahora las marcas son todas las del panel y pasan en la banda de abajo
   (`.nos-distrib__marcas`), y el sello se quitó a pedido del usuario. */
.nos-distrib__grid {
  max-width: 1130px;
  margin-inline: auto;
}
/* Una sola línea en escritorio (2026-09-29, pedido del usuario; antes
   `max-width:480px` + un corte forzado antes de "garantía"). */
.nos-distrib__title {
  font-size: clamp(20px, 1.7vw, 23px);
  font-weight: 600;
  line-height: 1.5;
  color: #444;
}
.nos-distrib__big {
  display: block;
  margin-top: 62px;
  font-size: clamp(58px, 6vw, 88px);
  font-weight: 600;
  line-height: 1;
  color: var(--accent);
}
/* Cuando el "+3" es la imagen real del ACTUAL (forma del glifo exacta). */
img.nos-distrib__big { height: clamp(48px, 4.6vw, 66px); width: auto; }
.nos-distrib__label {
  display: block;
  margin-top: 40px;
  font-size: clamp(16px, 1.3vw, 19px);
  font-weight: 400;
  color: #6b6b6b;
}
/* Marcas: la misma banda en movimiento de Clientes de Inicio
   (`.clientes__viewport` y hermanos, partials/banda-logos.php), al ancho del
   bloque de arriba y separada por una línea fina. */
.nos-distrib__marcas {
  max-width: 1130px;
  margin: 48px auto 0;
  padding-top: 40px;
  border-top: 1px solid #e5e7eb;
}

/* ---- MISIÓN / VISIÓN (fondo gris liso, sin líneas) ---- */
.nos-mv {
  background: #f5f7f6;
  padding: 72px 0 46px;
}
/* Contenido centrado ~1130px con márgenes laterales como el ACTUAL. */
.nos-mv__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 120px;
  max-width: 1130px;
}
.nos-mv__icon { width: 80px; height: auto; }
.nos-mv__rule { display: block; width: 140px; height: auto; margin: 42px 0 46px; }
.nos-mv__title {
  font-size: clamp(24px, 2.3vw, 30px);
  font-weight: 700;
  line-height: 1.1;
  color: var(--brand);
  margin-bottom: 26px;
}
.nos-mv__text {
  font-size: clamp(15px, 1.35vw, 18px);
  font-weight: 400;
  line-height: 1.6;
  color: #555;
  max-width: 505px;
}

/* ---- CITA (banner fijo, 2026-09-15: reemplaza la marquesina de contorno +
   texto sólido en movimiento a pedido del usuario) ---- */
/* Se conserva el fondo blanco y la línea gris fina arriba/abajo de la
   marquesina anterior. La idea de "tipografía enorme decorativa" del
   contorno se resuelve con una comilla grande en acento, fija en vez de
   en movimiento; el separador (`.nos-quote__sep`) se agrupó con el de los
   heroes del sitio y el banner de Inicio — ver `.nos-hero__sep` y
   hermanos, mismo motivo de 110×4px. */
.nos-quote {
  position: relative;
  overflow: hidden;
  padding: clamp(44px, 7vw, 68px) 24px;
  margin: 8px 0 38px;
  background: #fff;
  border-top: 1px solid #e2e2e2;
  border-bottom: 1px solid #e2e2e2;
  text-align: center;
}
.nos-quote__inner { position: relative; max-width: 660px; margin: 0 auto; }
/* La comilla se posiciona relativa a `.nos-quote__inner` (no a `.nos-quote`,
   que ocupa todo el ancho de la sección) — code review 2026-09-15: un
   offset fijo medido para el ancho tope de 660px del bloque de texto se
   desalineaba entre 521-707px de viewport, el rango en el que ese bloque
   ya se angostó por debajo de su max-width pero la comilla todavía es
   visible. Anclarla al contenedor real (que sí tiene el ancho verdadero
   en cualquier viewport) lo vuelve correcto en todos los anchos. */
.nos-quote__mark {
  position: absolute;
  top: -52px;
  left: 0;
  transform: translateX(-94px);
  font-size: 96px;
  font-weight: 700;
  line-height: 1;
  /* var(--accent) al 18% de opacidad */
  color: rgba(36, 222, 121, .18);
  font-family: var(--font);
  pointer-events: none;
}
.nos-quote__text {
  color: var(--brand);
  font-weight: 700;
  font-size: clamp(21px, 3vw, 30px);
  line-height: 1.4;
  margin: 0;
}
@media (max-width: 520px) {
  .nos-quote__mark { display: none; }
}

/* ---- GALERÍA ---- */
.nos-galeria { padding: 8px 0 72px; }
.nos-galeria__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 28px;
}
.nos-galeria__item {
  margin: 0;
  aspect-ratio: 281 / 236;
  overflow: hidden;
}
.nos-galeria__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---- Responsive ---- */
/* Los cortes de línea forzados (para clonar la distribución del ACTUAL en
   escritorio) se desactivan al angostar para que el texto reflowe solo. */
@media (max-width: 760px) {
  .nos-intro__text .brk,
  .nos-mv__text .brk { display: none; }
}
@media (max-width: 1024px) {
  /* Mismo reset que `.serv-hero__inner` (ver sección Servicios): sin esto,
     `margin-left:12%` combinado con `max-width:640px` deja el hero indentado
     y más angosto que el resto del contenido en vez de usar el ancho
     completo — se detectó recién en code review, no en vivo con el usuario. */
  .nos-hero__inner { margin-left: 0; max-width: 100%; }
  .nos-intro__block { margin-inline: auto; }
  .nos-mv__grid { gap: 60px; }
}
@media (max-width: 860px) {
  .nos-mv__grid { grid-template-columns: 1fr; gap: 40px; }
  .nos-galeria__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .nos-distrib__marcas { margin-top: 36px; padding-top: 28px; }
  .nos-galeria__grid { grid-template-columns: 1fr; }
}

/* Botón sólido con triángulo de acento animado en la esquina (medido del
   ACTUAL: clase inline "btn-expansion-esquina" de la página Servicios —
   distinto del .btn--corner-accent de Figma, que es de contorno). */
/* position/overflow/z-index/::after/:hover::after: ver el selector
   agrupado junto a `.sd-related__link` (sección "Botones", arriba). */
.btn--solid-expand {
  padding: 16px 36px;
  background: #21cb6f;
  color: #fff;
  font-weight: 700;
  font-size: 18px;
  border: 0;
  border-radius: 0;
  transition: background .4s ease-in-out;
}
.btn--solid-expand::after { background: var(--accent); }

/* =====================================================================
   SERVICIOS (app/Views/site/servicios.php) — clases .serv-*
   ===================================================================== */

/* ---- HERO ----
   Medido en vivo en ACTUAL: título/subtítulo/línea van "horneados" como
   texto BLANCO sobre PNG transparente (Container-3.png), pensado para
   verse sobre la foto de fondo (Section-3.png, tinte verde ya incluido) —
   por eso parecían invisibles al mirar la imagen sola sobre blanco. Aquí
   se reproducen como texto real (regla del proyecto) sobre la misma foto. */
.serv-hero {
  position: relative;
  background: var(--hero-bg);
  padding: 70px 0 93px;
  overflow: hidden;
  /* min-height 300px (2026-09-13, pedido del usuario): mismo alto total que
     el hero de Nosotros — antes 277.4px (dependía solo del contenido). El
     título ya arrancaba a 70px del borde superior (sin cambios, ya era el
     valor de referencia que ahora también usan Nosotros/Detalle). */
  min-height: 300px;
}
/* Foto de fondo real (imagen <img>, no CSS background-image: la CSP del
   sitio prohíbe style="" inline, así que una URL dinámica del CMS no puede
   pasarse como background-image por atributo — se apila como capa). */
.serv-hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.serv-hero > .container-wide { position: relative; z-index: 1; }
.serv-hero__inner { margin-left: 12%; max-width: 640px; }
/* Título/línea/subtítulo: ver el selector agrupado junto a `.nos-hero__
   title` (arriba, sección Nosotros) — `.serv-hero__title/__sep/__subtitle`
   se estilan ahí junto con `.sd-`/`.cont-`. Orden título → línea →
   descripción (2026-09-13): la línea va INMEDIATAMENTE debajo del título
   (antes la descripción se interponía). */
/* Entrada suave (ACTUAL anima este bloque con fadeInDown al cargar). */
.reveal-in { animation: servHeroIn .7s ease both; }
@keyframes servHeroIn {
  from { opacity: 0; transform: translateY(-14px); }
  to   { opacity: 1; transform: none; }
}

/* ---- TARJETAS DE SERVICIO (título | foto | descripción+enlace) ---- */
.serv-lista { background: #fff; }
.serv-row { padding: 40px 0; }
/* Medido del CSS inline de ACTUAL (clase "seccion-interactiva", ancho real
   de columna 1040px — NO toda la fila): el tinte y el hover se limitan al
   ancho del contenido, no al 100% de la fila. */
.serv-row__grid {
  display: grid;
  grid-template-columns: 1fr 289px 1fr;
  align-items: center;
  gap: clamp(24px, 3.2vw, 48px);
  max-width: 1050px;
  margin-inline: auto;
  /* ACTUAL trae relleno asimétrico (0 izq / 40px der) dentro de la caja de
     hover; se pareja a 40px en ambos lados para que el texto no quede
     pegado a ningún borde (medido forzando el estado :hover en vivo). */
  padding: 20px 40px;
  transition: background-color .4s;
}
.serv-row__grid:hover { background-color: rgb(238, 249, 243); }
/* grid-column explícito en las 3 celdas: si a un servicio le falta la foto
   (campo `imagen` vacío en el CMS), .serv-row__photo no se imprime y, sin
   esto, el auto-placement de grid corre el título/descripción a las
   columnas 1-2 en vez de 1 y 3. */
.serv-row__title {
  grid-column: 1;
  font-size: clamp(20px, 1.7vw, 25px);
  font-weight: 700;
  line-height: 1.35;
  color: #001f0b;
}
.serv-row__title-sep {
  display: block;
  width: 81px;
  height: 5px;
  margin-top: 14px;
  background: var(--accent);
}
.serv-row__photo {
  grid-column: 2;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  transition: transform .4s cubic-bezier(.2, 1, .3, 1);
}
/* ACTUAL usa -25px (confirmado, única regla, sin otra que la pise); se
   reduce a -16px por pedido explícito del usuario — desviación deliberada
   del valor medido, no un error de medición. */
.serv-row__grid:hover .serv-row__photo { transform: translateY(-16px); }
.serv-row__photo img { width: 100%; height: 100%; object-fit: cover; }
.serv-row__body {
  grid-column: 3;
}
.serv-row__text {
  font-size: clamp(15px, 1.05vw, 16px);
  font-weight: 400;
  line-height: 1.8;
  color: #555;
}
.serv-row__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 22px;
  padding-bottom: 6px;
  position: relative;
  font-size: 18px;
  color: var(--accent);
  border-bottom: 2px solid var(--accent);
  transition: color .3s;
}
.serv-row__link .btn__arrow { font-weight: 400; }
.serv-row__grid:hover .serv-row__link { color: #2c567a; }

/* ---- GESTIÓN INTEGRAL DE PERMISOS (fondo gris liso, sin líneas) ---- */
.serv-permisos { background: #f5f7f6; padding: 72px 0 84px; }
/* Misma grilla de 3 columnas que .serv-permisos__grid (más abajo), para que
   el botón quede alineado con el inicio de la 3ª tarjeta en vez de pegado
   al borde derecho del contenedor. */
.serv-permisos__head {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 48px;
  align-items: end;
  max-width: 1250px;
  margin-inline: auto;
  margin-bottom: 56px;
}
/* Ancho real medido de la columna de título/subtítulo en ACTUAL (~749px),
   no todo el ancho disponible antes del botón. */
.serv-permisos__intro { grid-column: 1 / 3; max-width: 750px; }
.serv-permisos__cta { grid-column: 3; justify-self: start; }
.serv-permisos__title {
  font-size: clamp(28px, 2.9vw, 38px);
  font-weight: 700;
  line-height: 1.15;
  color: #001f0b;
}
.serv-permisos__subtitle {
  margin-top: 14px;
  font-size: clamp(20px, 2.1vw, 28px);
  font-weight: 400;
  line-height: 1.4;
  color: #555;
}
.serv-permisos__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 56px 48px;
  max-width: 1250px;
  margin-inline: auto;
}
.serv-step__icon { display: block; height: 56px; width: auto; }
.serv-step__rule { display: block; width: 134px; height: auto; margin: 30px 0 28px; }
.serv-step__title {
  font-size: clamp(19px, 1.6vw, 23px);
  font-weight: 700;
  line-height: 1.3;
  color: #001f0b;
}
.serv-step__text {
  margin-top: 14px;
  font-size: clamp(15px, 1.05vw, 16px);
  font-weight: 400;
  line-height: 1.75;
  color: #555;
}

/* ---- Responsive ---- */
@media (max-width: 1024px) {
  .serv-hero__inner { margin-left: 0; max-width: 100%; }
  .serv-row__grid { grid-template-columns: 1fr; max-width: 520px; }
  .serv-row__title { grid-column: auto; order: 1; }
  .serv-row__photo { grid-column: auto; order: 2; max-width: 340px; }
  .serv-row__body { grid-column: auto; order: 3; }
  .serv-permisos__grid { grid-template-columns: repeat(2, 1fr); }
  .serv-permisos__head { grid-template-columns: 1fr; row-gap: 24px; }
  .serv-permisos__intro { grid-column: auto; }
  .serv-permisos__cta { grid-column: auto; }
}
@media (max-width: 640px) {
  .serv-permisos__grid { grid-template-columns: 1fr; }
}

/* =====================================================================
   DETALLE DE SERVICIO (app/Views/site/servicio-detalle.php) — clases .sd-*

   Estructura y contenedor medidos en vivo de las 6 páginas reales de
   ACTUAL (p. ej. indasasv.com/ingenieria-y-diseno/,
   indasasv.com/ppa-y-financiamiento/ — las 6 existen, ver comentario al
   inicio de la vista): hero con título y subtítulo CENTRADOS (no a la
   izquierda); cuerpo en una grilla de 2 columnas donde SOLO las primeras
   dos filas (foto+frase | texto+enlaces) usan la columna derecha — de ahí
   en adelante (tarjetas, banner, preguntas) todo queda en el ancho de la
   columna izquierda nada más, la derecha se ve en blanco, tal cual ACTUAL.

   El contenedor es `.container-detail` (1200px de CONTENIDO real, no de
   `max-width`): medido en vivo a 1600 y 1920px de viewport, la caja de
   contenido de ACTUAL mide 1200px FIJO en ambos anchos (no un porcentaje
   fluido). No se reusa `.container` (1180px) porque ese `max-width` ya
   incluye su `padding-inline:24px` (todo el sitio usa `box-sizing:
   border-box`), así que el contenido real que deja adentro es 1180-48=
   1132px — 68px más angosto de lo medido, y por eso una primera pasada
   se veía notoriamente más chica que ACTUAL (tarjetas, banner, fotos,
   todo escalado hacia abajo). `.container-detail` usa `max-width:1248px`
   (el wrapper de fila medido en ACTUAL) + el mismo `padding-inline:24px`,
   para que el CONTENIDO quede en 1200px exactos. */
.container-detail { width: 100%; max-width: 1248px; margin-inline: auto; padding-inline: 24px; }

/* ---- HERO (rediseño 2026-09-13, corregido el mismo día — aclaración del
   usuario): copia EXACTA del hero de Servicios (posición horizontal Y
   vertical, tamaño de letra, espaciado) — YA NO comparte `.container-detail`
   con el cuerpo (esa fue la primera pasada, alineaba con `.sd-block__title`
   en vez de con Servicios). Usa la misma estructura que `.serv-hero`:
   `.container-wide` por fuera + `.sd-hero__inner` con `margin-left:12%` +
   `max-width:640px` por dentro (ver `.uw-wide .sd-hero__inner` más abajo
   para el mismo override que usa `.serv-hero__inner` en ultra-wide). ---- */
.sd-hero {
  position: relative;
  isolation: isolate;
  background: var(--hero-bg);
  overflow: hidden;
  /* padding-top 70px + min-height 300px (2026-09-13, pedido del usuario):
     mismo nivel de título (70px, el de Servicios) y mismo alto total
     (300px, el de Nosotros) que las otras 2 páginas con hero. */
  padding: 70px 0 56px;
  min-height: 300px;
}
.sd-hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -1;
}
.sd-hero__inner { margin-left: 12%; max-width: 640px; }
/* Título/línea/subtítulo: ver el selector agrupado junto a `.nos-hero__
   title` (sección Nosotros, arriba en este archivo) — compartido por las
   4 páginas con hero. */

/* ---- CUERPO ----
   Grilla explícita: cada bloque declara su propia columna (y a veces fila)
   en vez de depender del auto-flow, para que el layout no se rompa si
   falta algún campo opcional (p. ej. un servicio sin foto lateral). */
.sd-body { background: #fff; padding: 64px 0 80px; }
.sd-grid {
  display: grid;
  grid-template-columns: 2.13fr 1fr;
  column-gap: 48px;
  /* 60px = promedio medido en vivo de las 4 separaciones reales entre filas
     en ACTUAL (foto/frase → texto: 80px; texto → tarjetas: 51px; tarjetas
     → banner: 63px; banner → preguntas: 68px). El grid usa un solo valor
     para las 4 filas; antes eran 40px (+ otros 40px sueltos por
     `margin-bottom` en `.sd-features`/`.sd-banner`, ver abajo — quedaba
     inconsistente entre filas y más angosto que ACTUAL en general). */
  row-gap: 60px;
  /* stretch (no "start"): en ACTUAL la foto y la tarjeta verde miden casi
     lo mismo de alto (510 vs 509px medidos) porque la fila las estira por
     igual — no es casualidad de contenido, es el comportamiento por
     defecto de la fila. "Otros servicios" (fila 2, columna derecha) sí
     necesita quedarse compacta arriba en vez de estirarse — ver abajo. */
  align-items: stretch;
}
.sd-photo     { grid-column: 1; grid-row: 1; }
.sd-quote     { grid-column: 2; grid-row: 1; }
.sd-showcase  { grid-column: 1 / -1; grid-row: 1; }
.sd-textblock { grid-column: 1; grid-row: 2; }
.sd-features  { grid-column: 1; grid-row: 3; }
.sd-banner    { grid-column: 1; grid-row: 4; }
.sd-faq       { grid-column: 1; grid-row: 5; }
/* `.sd-side` (corregido 2026-09-13, dos rondas): envuelve "Otros servicios"
   + "Déjanos tu información" (nuevo) en UN SOLO ítem de grid — columna
   derecha, desde la fila 2 hasta la última (`2 / -1`), `align-self:start`.
   Intento anterior: cada uno como ítem de grid separado con su propio
   `grid-row` fijo (`.sd-related` en 2/span2, `.sd-contact` en 4/span2) —
   pero esas filas se dimensionan por el contenido de la columna IZQUIERDA
   (texto/tarjetas/banner), no por "Otros servicios" (5 botones, ~490px), así
   que quedaba un hueco de ~273px entre ambos bloques (el resto de esas
   filas que "Otros servicios" no llegaba a llenar, + el row-gap). Con
   `display:flex;flex-direction:column` DENTRO de `.sd-side`, los dos
   bloques se apilan por su alto REAL con un gap fijo (60px, mismo valor
   que el row-gap del grid) — completamente independiente de cómo se
   acomode la columna izquierda. */
.sd-side {
  grid-column: 2;
  /* `span 4` (filas 2,3,4,5), NO `2 / -1`: el grid no tiene
     `grid-template-rows` explícito (las 5 filas son implícitas, generadas
     por dónde cada ítem se coloca) — `-1` solo funciona de forma fiable
     contra la ÚLTIMA LÍNEA DEL GRID EXPLÍCITO, que acá no existe (0 filas
     explícitas), así que resolvía a un span inválido (2/1) y el navegador
     reubicaba el ítem por auto-placement en la fila 1 junto a `.sd-quote`
     — eso inflaba la fila 1 a ~1026px para caber el contenido de
     `.sd-side`, y `.sd-photo` (con `aspect-ratio` + `align-items:stretch`)
     se estiraba a esa altura, desbordando su columna (ancho > columna).
     `span 4` referencia un número de filas, no una línea, así que no
     depende de que el grid tenga filas explícitas — funciona seguro. */
  grid-row: 2 / span 4;
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: 60px;
}

/* border-radius:0 — medido en ACTUAL (fusion-imageframe, borderRadius
   computado = 0px), no los 4px de --r que se usan en el resto del sitio. */
.sd-photo { border-radius: 0; overflow: hidden; aspect-ratio: 800 / 520; }
.sd-photo img { width: 100%; height: 100%; object-fit: cover; }

/* ---- Imagen + frase en UN solo bloque (rediseño 2026-09-26, Figma) ----
   Solo cuando la imagen subida es la "compuesta" (apaisada, 2000×713, con el
   panel verde en diagonal YA dibujado en la imagen — ver la vista). El sitio
   no dibuja nada: pone la imagen a ancho completo y la frase encima, como
   texto real (editable desde el panel). Posición y tamaños medidos sobre la
   imagen del diseño (2000 px): el texto queda centrado en x = 80 % (caja de
   left:60% a right:0) y en el medio vertical; la frase mide 2,45 % del ancho,
   la línea verde 6,5 %, la marca 1,5 %. Todo en `cqw` (unidad de contenedor)
   para que el texto escale junto con la imagen y siga cayendo dentro del
   panel a cualquier ancho. Cada tamaño lleva antes un valor en px por si el
   navegador no soporta `cqw`. */
.sd-showcase {
  position: relative;
  margin: 0;
  overflow: hidden;
  border-radius: 0;
  aspect-ratio: 2000 / 713;
  background: var(--brand);
  container-type: inline-size;
}
.sd-showcase__img { display: block; width: 100%; height: 100%; object-fit: cover; }
.sd-showcase__text {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 60%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 5cqw;
  text-align: center;
  color: #fff;
}
.sd-showcase__quote {
  margin: 0;
  font-size: 26px; font-size: 2.45cqw;
  font-weight: 400;
  line-height: 1.25;
  text-wrap: balance;
}
.sd-showcase__sep {
  display: block;
  width: 68px; width: 6.5cqw;
  height: 3px;
  background: var(--accent);
  margin: 18px auto 14px; margin: 1.5cqw auto 1.25cqw;
}
/* max(13px, …): en tablet (721-870px) 1.5cqw solo daba ~10px, ilegible. */
.sd-showcase__brand { display: block; font-size: 16px; font-size: max(13px, 1.5cqw); font-weight: 400; letter-spacing: .01em; }
.sd-showcase__brand strong { font-weight: 700; }

/* La firma va en su propio bloque (`.sd-showcase__firma`): en escritorio no genera
   caja y sus hijos siguen apilados bajo la frase; en móvil se ubica aparte (abajo). */
.sd-showcase__firma { display: contents; }

/* En móvil la frase sobre la imagen quedaría diminuta (el panel verde de la foto mide
   ~110px de ancho y la frase saldría a ~10px), así que se separan (2026-09-26, pedido
   del usuario: "la firma sobre el verde de la imagen y solo la leyenda abajo"):
     - la FIRMA (línea verde + marca) sigue sobre el panel verde de la imagen, centrada
       en la misma zona que en escritorio (de left:60% a right:0, alto = el de la
       imagen, 713/2000 del ancho del bloque);
     - la FRASE pasa debajo, sola, sobre verde liso — un panel mucho más bajo.
   Los tamaños crecen con el ancho (clamp) hasta los de escritorio a ~720px. */
@media (max-width: 720px) {
  .sd-showcase { aspect-ratio: auto; display: flex; flex-direction: column; }
  .sd-showcase__img { height: auto; aspect-ratio: 2000 / 713; }
  /* El <figcaption> no genera caja: la frase es un ítem más de la columna y la firma
     se posiciona contra el bloque. */
  .sd-showcase__text { display: contents; }
  .sd-showcase__quote {
    padding: clamp(16px, 3.5vw, 26px) 20px clamp(18px, 4vw, 28px);
    font-size: clamp(17px, 3vw, 22px);
    line-height: 1.3;
    text-align: center;
  }
  .sd-showcase__firma {
    position: absolute;
    top: 0; left: 60%; right: 0;
    height: 32vw; height: 35.65cqw;   /* alto de la imagen (px de respaldo sin cqw) */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: #fff;
  }
  .sd-showcase__sep { width: clamp(36px, 9cqw, 56px); margin: 0 0 clamp(6px, 2cqw, 10px); }
  .sd-showcase__brand { font-size: clamp(12px, 3.4cqw, 16px); }
}

.sd-textblock .sd-block:last-child { margin-bottom: 0; }
.sd-block { margin-bottom: 40px; }
.sd-block__title {
  font-size: clamp(23px, 2vw, 30px);
  font-weight: 700;
  line-height: 1.2;
  color: #001f0b;
  margin-bottom: 14px;
}
.sd-block__text {
  font-size: clamp(15px, 1.05vw, 17px);
  line-height: 1.65;
  color: #555;
}

.sd-checklist { list-style: none; margin-top: 20px; display: flex; flex-direction: column; gap: 12px; }
.sd-checklist li { display: flex; align-items: flex-start; gap: 10px; font-size: 15px; color: #333; line-height: 1.5; }
/* Ícono real recortado de ACTUAL (ver icon-check.png) — no un check
   dibujado a mano. */
.sd-checklist__icon { flex-shrink: 0; display: block; width: 20px; height: 20px; margin-top: 1px; }

/* ---- Tarjetas "enfoque" (2 columnas, fondo gris liso) ----
   Tamaño medido en vivo del recorte real de ACTUAL (Container-5.png,
   800×309 a dos tarjetas): círculo de ícono ~80px, padding ~32-36px,
   título ~19px, texto ~15px/1.8 — una primera pasada usaba valores mucho
   más chicos (ícono 48px, padding 28px, título 17px) y las tarjetas
   quedaban visiblemente más pequeñas que en ACTUAL. */
.sd-features {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
}
.sd-feature { background: #f5f7f6; border-radius: var(--r); padding: 36px; }
/* El ícono YA es la imagen real recortada de ACTUAL (círculo gris incluido
   en el PNG, con su transparencia) — no hay que dibujar el círculo con CSS. */
.sd-feature__icon { display: block; width: 80px; height: 80px; margin-bottom: 28px; }
.sd-feature__title { font-size: 19px; font-weight: 700; color: #16211c; margin-bottom: 10px; }
.sd-feature__text { font-size: 17px; line-height: 1.8; color: #666; }

/* ---- Banner CTA (foto + degradado + título + botón) ---- */
/* border-radius:0 y alto ~257px — medido en ACTUAL (columna con
   background-image, 770×257 dentro de la columna izquierda de 784px). */
.sd-banner {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: 0;
  min-height: 257px;
  display: flex;
  align-items: center;
  /* Por si no hubiera imagen de fondo: el mismo tono oscuro del degradado (abajo). */
  background: #040907;
}
/* La imagen de fondo ya NO está fija en la vista (2026-09-26): se sube desde el
   panel en cada servicio (campo `banner_imagen`); la de fábrica es el espejo
   compartido `uploads-fallback/servicios/servicios-detalle-banner_imagen.webp`
   (la foto de abajo, en WebP). El degradado de `.sd-banner::after` se aplica
   sobre CUALQUIER foto: se sube la foto sola, sin oscurecer.

   object-position:0% 0% — medido en ACTUAL con getComputedStyle: la foto
   real usa `background-position:0% 0%` (ancla arriba-izquierda). Ahora
   la foto de fábrica es la COMPLETA de ACTUAL (1600×518, mismo aspecto
   ~3.09:1 que la caja del banner, ~3:1) con el texto horneado ELIMINADO
   por inpainting (ver ronda 8 en CLAUDE.md) en vez de un recorte que
   excluía la mitad izquierda — por eso ahora sí se puede anclar como
   ACTUAL: `cover` con este aspecto casi idéntico casi no recorta nada. */
.sd-banner__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 0% 0%; z-index: -2; }
/* Degradado ancho — valores REALES de ACTUAL (clase del propio `<style>`
   inline, leída de document.styleSheets, ver ronda 3): con la foto
   COMPLETA (no el recorte angosto de las rondas 3-7) el trabajador vuelve
   a estar lejos de la zona más oscura del degradado, como en ACTUAL, así
   que el degradado angosto de la ronda 7 ya no hace falta — se revierte a
   los stops originales. */
.sd-banner::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(90deg, rgba(4,9,7,.90) 0%, rgba(4,9,7,.62) 42%, rgba(4,9,7,.18) 72%, rgba(4,9,7,0) 100%);
}
.sd-banner__inner { padding: 40px; max-width: 480px; }
.sd-banner__title {
  color: #fff;
  font-size: clamp(19px, 1.7vw, 24px);
  font-weight: 300;
  line-height: 1.4;
  margin-bottom: 22px;
}
/* Botón del banner: en ACTUAL NO es una caja — es un link de texto verde
   con un subrayado que crece de 0 a 100% en hover y un pequeño
   desplazamiento (medido: clase real "boton-enlace-animado" de ACTUAL,
   leída de document.styleSheets). Nada de fondo sólido tipo .btn--solid-expand. */
.sd-banner__cta {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 10px;
  color: var(--accent);
  font-weight: 300;
  font-size: 16px;
  transition: transform .3s ease;
}
.sd-banner__cta::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 0;
  height: 2px;
  background: var(--accent);
  transition: width .4s ease-in-out;
}
.sd-banner__cta:hover { transform: translateX(5px); }
.sd-banner__cta:hover::after { width: 100%; }

/* ---- Preguntas frecuentes ---- */
.sd-faq { margin-bottom: 8px; }
.sd-faq__list { margin-top: 20px; border-top: 1px solid var(--line); }
.sd-faq__item { border-bottom: 1px solid var(--line); }
button.sd-faq__q {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 4px;
  background: none;
  border: 0;
  cursor: pointer;
  text-align: left;
  font-family: var(--font);
  font-size: 20px;
  font-weight: 700;
  color: #16211c;
  transition: color .2s ease;
}
button.sd-faq__q:hover { color: var(--accent-ink); }
p.sd-faq__q--static { display: flex; align-items: center; gap: 14px; padding: 18px 4px; font-size: 20px; font-weight: 700; color: #16211c; }
.sd-faq__arrow {
  flex-shrink: 0;
  display: inline-block;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--accent-ink);
  border-bottom: 2px solid var(--accent-ink);
  transform: rotate(-45deg);
  transition: transform .25s ease;
}
.sd-faq__q[aria-expanded="true"] .sd-faq__arrow { transform: rotate(45deg); }
.sd-faq__a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .3s ease;
}
.sd-faq__a > div { overflow: hidden; }
.sd-faq__item.is-open .sd-faq__a { grid-template-rows: 1fr; }
/* La respuesta puede traer párrafos y listas con viñetas (SiteContent::
   textoEnBloques): cada bloque lleva su espacio y solo el último cierra con 20px. */
.sd-faq__a p, .sd-faq__a ul { margin: 0; padding: 0 4px 12px 22px; font-size: 15px; line-height: 1.65; color: #555; }
.sd-faq__a > div > :last-child { padding-bottom: 20px; }
.sd-faq__a ul { padding-left: 42px; list-style: disc; }
.sd-faq__a li::marker { color: var(--accent); }
.sd-faq__a li + li { margin-top: 4px; }

/* ---- Frase destacada + otros servicios (columna derecha) ----
   La tarjeta verde en ACTUAL es una imagen (368×509/553) del mismo alto
   que la foto vecina — border-radius:0 (medido, fusion-imageframe) y
   estirada por la fila (`.sd-grid` ahora usa `align-items:stretch`, ver
   arriba) en vez de encogerse al alto de su propio texto.

   Color, tamaño y separador RE-medidos por canal alpha sobre el PNG real
   (decor.png / Background-1 y equivalentes) — la primera pasada usaba
   `var(--hero-bg)` (#052213, muy oscuro) y un texto/separador chicos
   inventados a ojo:
     - Fondo real: #083820 exacto = `var(--brand)`, NO `--hero-bg`.
     - Texto: centrado (cada línea centrada en el ancho de la tarjeta),
       blanco casi puro (~#fbfbfb), ~32px con line-height 1.4 (medido por
       bandas de píxeles claros: 4 líneas de ~28px de alto con salto de
       ~51px entre líneas, escalado al ancho real mostrado).
     - Separador: 87×5px (no 40×3px), color exacto `--accent`, CENTRADO
       horizontalmente (no pegado a la izquierda). */
.sd-quote {
  background: var(--brand);
  color: #fff;
  border-radius: 0;
  padding: 34px 30px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
}
.sd-quote__text { font-size: clamp(24px, 2.7vw, 32px); font-weight: 300; line-height: 1.4; }
.sd-quote__sep { display: block; width: 87px; height: 5px; background: var(--accent); margin: 24px auto 18px; }
.sd-quote__brand { display: block; font-size: 19px; font-weight: 400; letter-spacing: .03em; }
.sd-quote__brand small { display: block; font-size: 16px; font-weight: 300; color: rgba(255,255,255,.7); letter-spacing: .02em; margin-top: 2px; }

.sd-related { display: flex; flex-direction: column; gap: 20px; }
/* Recreación EXACTA de la clase real de ACTUAL "btn-expansion-esquina"
   (leída de document.styleSheets, no adivinada): fondo blanco, texto
   negro CENTRADO, borde gris 1px, triángulo verde en la esquina
   inferior-derecha que en hover se expande con clip-path hasta cubrir
   todo el botón, y el texto pasa a blanco. */
/* position/overflow/z-index/::after (clip-path)/:hover::after: ver el
   selector agrupado en la sección "Botones", arriba del archivo. */
.sd-related__link {
  display: flex;
  width: 100%;
  box-sizing: border-box;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 24px 36px;
  background-color: #fff;
  font-size: 18px;
  font-weight: 700;
  text-align: center;
  border: 1px solid #b3b3b3;
  border-radius: 0;
  cursor: pointer;
  transition: color .4s ease-in-out;
  color: #111;
}
.sd-related__link::after { background-color: #61de82; }
.sd-related__link:hover { color: #fff; }
.sd-related__link .btn__arrow { font-weight: 400; }

/* ---- "Déjanos tu información" (formulario de contacto, 2026-09-13) ----
   Tarjeta con borde fino gris, blanco por dentro — mismo criterio de
   inputs "línea inferior" que ya usa el formulario del footer
   (`.site-footer__form-row input`), adaptado a fondo claro (footer es
   fondo oscuro). El botón reusa `.btn.btn--primary` (mismo verde sólido
   que el resto del sitio) en vez de inventar un estilo nuevo. */
/* ---- Tarjeta de formulario compartida por `.sd-contact` ("Déjanos tu
   información", Detalle de servicio) y `.cont-form` (Contáctanos) — mismo
   borde/padding/tipografía/inputs "línea inferior" en las dos, code review
   2026-09-15: antes cada una repetía las ~20 líneas comunes por separado y
   ya habían divergido en un detalle (`box-sizing:border-box` en una, no en
   la otra — sin efecto visual hoy porque ninguna de las dos tiene padding
   horizontal en el input, pero inconsistente igual). Cada una conserva
   aparte solo lo que de verdad es distinto: el botón (`.sd-contact__
   submit` compacto vs `.cont-form__submit` ancho completo), la fila de 2
   columnas de `.cont-form__row`, y el alto del textarea (2 líneas en una,
   3 en la otra — según su propio atributo `rows`). */
.sd-contact,
.cont-form {
  border: 1px solid #b3b3b3;
  padding: 40px;
  background: #fff;
}
.sd-contact__title,
.cont-form__title {
  font-size: clamp(22px, 2vw, 28px);
  font-weight: 700;
  color: #16211c;
  margin-bottom: 28px;
}
.sd-contact__field,
.cont-form__field { margin-bottom: 22px; }
.sd-contact__field:last-of-type,
.cont-form__field:last-of-type { margin-bottom: 32px; }
.sd-contact input,
.sd-contact textarea,
.cont-form input,
.cont-form textarea {
  display: block;
  width: 100%;
  box-sizing: border-box;
  border: none;
  border-bottom: 1px solid #ccc;
  background: transparent;
  padding: 8px 0;
  font-family: var(--font);
  font-size: 16px;
  color: #16211c;
  resize: none;
  transition: border-color .2s ease;
}
.sd-contact input::placeholder,
.sd-contact textarea::placeholder,
.cont-form input::placeholder,
.cont-form textarea::placeholder { color: #9a9a9a; }
.sd-contact input:focus,
.sd-contact textarea:focus,
.cont-form input:focus,
.cont-form textarea:focus { outline: none; border-bottom-color: var(--accent); }

.sd-contact__form { display: flex; flex-direction: column; }
/* Alto explícito de N líneas (pedido del usuario) — el atributo HTML
   `rows` a veces no basta por sí solo si algo más en la cascada afecta el
   cálculo del alto por línea; con `min-height` calculado sobre el mismo
   font-size/line-height de arriba (16px, line-height 1.5 heredado del
   body) queda garantizado sin importar el navegador. `.sd-contact` usa
   `rows="3"` en su textarea, `.cont-form` también `rows="3"` — mismo
   multiplicador en las dos (antes `.cont-form` decía `*2`, desalineado
   con su propio `rows="3"`; sin efecto visible porque `rows` ya rendía
   más alto que ese piso, pero incorrecto igual). */
.sd-contact textarea,
.cont-form textarea { min-height: calc(16px * 1.5 * 3); line-height: 1.5; }
.sd-contact__submit { align-self: flex-start; font-weight: 700; }

/* ---- Responsive ----
   Una sola columna: todo vuelve a `grid-column:1` y a filas correlativas
   en el orden del DOM (foto, frase, texto, tarjetas, banner, preguntas) y,
   al final de todo, otros servicios y el formulario de contacto. */
@media (max-width: 1024px) {
  /* Mismo reset que `.serv-hero__inner` (ver sección Servicios) — sin esto
     el hero queda indentado y más angosto que el resto del contenido en vez
     de usar el ancho completo (detectado en code review, no en vivo con el
     usuario). */
  .sd-hero__inner { margin-left: 0; max-width: 100%; }
  .sd-grid { grid-template-columns: 1fr; row-gap: 28px; }
  .sd-photo, .sd-quote, .sd-showcase, .sd-textblock, .sd-side,
  .sd-features, .sd-banner, .sd-faq { grid-column: 1; grid-row: auto; }
  /* "Otros servicios" y "Déjanos tu información" al final de la página, no en
     medio (2026-09-28, pedido del usuario): `.sd-side` deja de ser caja, así
     los dos pasan a ser filas del grid, y `order` los manda después de las
     preguntas frecuentes, en ese orden (el del DOM entre los dos). */
  .sd-side { display: contents; }
  .sd-related, .sd-contact { order: 1; }
}
@media (max-width: 640px) {
  .sd-features { grid-template-columns: 1fr; }
  .sd-banner__inner { padding: 28px; max-width: 100%; }
  .sd-contact { padding: 28px; }
}

/* =====================================================================
   CONTÁCTANOS — página nueva, NO existe en ACTUAL (viene del Figma del
   proyecto). "No hace falta nada especial para ultra-wide" (ver nota de
   CLAUDE.md sobre páginas nuevas): los clamp() de abajo ya topan antes de
   1920px, así que el zoom global los escala bien sin reglas `.uw-wide`.
   ===================================================================== */

/* ---- HERO — mismo patrón EXACTO que `.serv-hero`/`.sd-hero` (ver esas
   secciones para la explicación completa): título → línea → descripción,
   alineado a la izquierda, `.container-wide` + `.cont-hero__inner
   {margin-left:12%;max-width:640px}`. Se duplica el bloque en vez de
   reusar la clase `.serv-hero` porque cada página necesita su propia
   imagen de fondo (`<img class="cont-hero__bg">`, distinta URL del CMS). */
.cont-hero {
  position: relative;
  background: var(--hero-bg);
  padding: 70px 0 93px;
  overflow: hidden;
  min-height: 300px;
}
.cont-hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.cont-hero > .container-wide { position: relative; z-index: 1; }
.cont-hero__inner { margin-left: 12%; max-width: 640px; }
/* Título/línea/subtítulo: ver el selector agrupado junto a `.nos-hero__
   title` (sección Nosotros, arriba en este archivo) — compartido por las
   4 páginas con hero. */

/* ---- DATOS DE CONTACTO (tarjeta verde) + FORMULARIO "Déjanos tu
   información" (Figma: franja con la info real de la empresa a la
   izquierda — MISMO dato que el footer global, `global.contacto.*` /
   `global.redes.*`, ver CLAUDE.md regla #1 — y el formulario a la
   derecha). El formulario reusa el criterio "línea inferior" de
   `.sd-contact` (Detalle de servicio). ---- */
.cont-lead { background: #fff; padding: 80px 0; }
.cont-lead__grid {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 48px;
  align-items: stretch;
}
.cont-info {
  background: var(--brand);
  color: #fff;
  padding: 48px 40px;
  display: flex;
  flex-direction: column;
}
/* Tipografía ajustada 2026-09-14 contra captura del Figma (antes tenía la
   jerarquía de color INVERTIDA): el título es bien grande; la ETIQUETA
   ("Teléfono", "WhatsApp"...) va casi blanca pura, y el VALOR ("(+503)...",
   el correo, la dirección) va apagado/tenue — no al revés como estaba. */
.cont-info__title { font-size: clamp(28px, 2.4vw, 34px); font-weight: 700; margin-bottom: 32px; }
.cont-info__block { margin-bottom: 36px; }
.cont-info__label { font-size: 16px; font-weight: 400; color: rgba(255, 255, 255, .92); margin-bottom: 8px; }
.cont-info__value { font-size: 16px; font-weight: 400; color: rgba(255, 255, 255, .55); margin-bottom: 18px; }
.cont-info__value a { color: inherit; }
.cont-info__social { display: flex; gap: 14px; list-style: none; margin-top: auto; padding-top: 14px; }
.cont-info__social img { display: block; width: 32px; height: 32px; }

/* Estilos comunes con `.sd-contact` (borde/padding/título/inputs/foco):
   ver el selector agrupado junto a `.sd-contact` (Detalle de servicio,
   arriba en este archivo). Acá solo lo que es propio de esta página. */
.cont-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.cont-form__submit { width: 100%; justify-content: center; font-weight: 700; }

/* ---- ALCANCE REGIONAL — mapa real interactivo (Leaflet + OpenStreetMap,
   ver public/assets/js/site.js e index.php para la CSP). El pin es un
   `L.divIcon` con esta clase (no una imagen: evita depender de los PNG de
   marcador por defecto de Leaflet para un color de marca simple). ---- */
/* Padding asimétrico (pedido del usuario, captura marcando el hueco):
   el mapa es full-bleed y debe tocar el borde INFERIOR de la sección (que
   linda directo con el footer) — solo se conserva el espacio ARRIBA
   (antes del título) y el `margin-top:40px` propio de `.cont-map` entre el
   subtítulo y el mapa. */
.cont-map-section { background: #f5f7f6; padding: 80px 0 0; text-align: center; }
.cont-map-section__title { font-size: clamp(24px, 2vw, 30px); font-weight: 700; color: var(--brand); }
.cont-map-section__subtitle { margin-top: 10px; font-size: 16px; color: #666; }
.cont-map {
  /* 100% del ancho de pantalla (pedido del usuario): el mapa ya NO va
     dentro de `.container` (que sí envuelve el título/subtítulo) — es
     hermano directo de `.cont-map-section`, que no tiene padding
     horizontal ni max-width, así que `width:100%` alcanza para llegar de
     borde a borde sin el truco `100vw` (que cuenta la scrollbar como parte
     del viewport y puede generar un desborde horizontal de unos px). */
  width: 100%;
  margin: 40px 0 0;
  height: 460px;
  border-top: 1px solid #d8dcda;
  border-bottom: 1px solid #d8dcda;
  background: #eef2f0; /* visible mientras cargan los tiles */
  text-align: left; /* Leaflet no hereda el center del contenedor */
}
/* Mapa borroso en ultra-wide, code review 2026-09-15 — verificado en vivo:
   bajo el `zoom` ambiental (>1920px), `#cont-map.clientWidth` (lo que
   Leaflet mide para decidir cuántos tiles pedir) queda en el tamaño
   ANTES del zoom (p. ej. 1912px a 3440px de viewport real), mientras que
   su tamaño PINTADO en pantalla ya es el zoomeado (3424.8px) — Leaflet
   arma el mapa para 1912px y el navegador lo estira x1.79 al pintarlo,
   de ahí el desenfoque. Cancelar el zoom ambiental SOLO acá
   (`zoom:1/factor`, factor expuesto como `--uw-zoom` por
   ultrawide-zoom.js) no reduce el tamaño visual (`width:100%` se
   re-resuelve contra el padre en el nuevo espacio local) pero sí hace
   que `clientWidth` vuelva a coincidir con el tamaño pintado real —
   confirmado midiendo ambos antes/después. `site.js` llama
   `map.invalidateSize()` después de esto para que Leaflet vuelva a medir
   y pida los tiles correctos. */
.uw-wide .cont-map { zoom: calc(1 / var(--uw-zoom, 1)); }
.cont-map__pin {
  width: 26px;
  height: 26px;
  border-radius: 50% 50% 50% 0;
  background: var(--accent);
  border: 3px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .4);
  transform: rotate(-45deg);
}
@media (max-width: 1024px) {
  .cont-hero__inner { margin-left: 0; max-width: 100%; }
  .cont-lead__grid { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .cont-form__row { grid-template-columns: 1fr; }
  .cont-info, .cont-form { padding: 32px 24px; }
  .cont-map { height: 340px; }
}

/* =====================================================================
   CALCULADORA (app/Views/site/calculadora.php) — clases .calc-*

   Página nueva basada en el Figma del proyecto (nodo "Calculadora"), no en
   una réplica en vivo de ACTUAL — mismo criterio que Contáctanos. "No hace
   falta nada especial para ultra-wide" (ver nota de CLAUDE.md sobre
   páginas nuevas): el único ajuste `.uw-wide` que necesita es el que ya
   comparte con las otras 4 heroes (ver selector agrupado, sección
   Detalle de servicio) — el resto de la página (tarjeta de formulario
   angosta y centrada) se ve bien igual de balanceada en cualquier ancho,
   no hace falta ensancharla como se hizo con Nosotros/Servicios/Detalle.
   ===================================================================== */

/* ---- HERO — mismo patrón EXACTO que `.serv-hero`/`.sd-hero`/`.cont-hero`
   (ver esas secciones para la explicación completa): título → línea →
   descripción, alineado a la izquierda, `.container-wide` + `.calc-hero__
   inner{margin-left:12%;max-width:640px}`. Se duplica el bloque en vez de
   reusar `.serv-hero` porque esta página necesita su propia imagen de
   fondo (`<img class="calc-hero__bg">`, distinta URL del CMS). ---- */
.calc-hero {
  position: relative;
  background: var(--hero-bg);
  padding: 70px 0 93px;
  overflow: hidden;
  min-height: 300px;
}
.calc-hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.calc-hero > .container-wide { position: relative; z-index: 1; }
.calc-hero__inner { margin-left: 12%; max-width: 640px; }
/* Título/línea/subtítulo: ver el selector agrupado junto a `.nos-hero__
   title` (sección Nosotros, arriba en este archivo) — compartido por las
   5 páginas con hero. */

/* ---- COTIZA TU FACTURA — tarjeta de formulario centrada. A diferencia de
   `.sd-contact`/`.cont-form` (placeholder como única guía, sin <label>
   visible), el Figma de esta página muestra una etiqueta arriba de CADA
   campo — por eso es un bloque propio, no se suma al selector agrupado de
   esas dos tarjetas. (Corrección 2026-09-22: la línea inferior sí es el
   mismo criterio que esas dos — ver `.calc-form input[...]` más abajo, un
   ajuste posterior la cambió de borde completo a línea inferior; lo que
   sigue distinto de verdad es el `<label>` visible y el padding/tamaño
   propios de esta tarjeta, no el estilo de borde.) */
.calc-form-section { background: #f5f7f6; padding: 80px 0; }
.calc-form-section__head { max-width: 560px; margin: 0 auto 40px; text-align: center; }
/* Rediseño 2026-09-26: antetítulo y título más chicos, como el diseño (a 1366px:
   antetítulo ~12px, título ~25px — antes 15px y 38px). */
.calc-form-section__eyebrow {
  font-size: 13px;
  font-weight: 700;
  color: var(--accent-ink);
  text-transform: uppercase;
  letter-spacing: .06em;
  margin-bottom: 8px;
}
.calc-form-section__title {
  font-size: clamp(24px, 1.9vw, 30px);
  font-weight: 700;
  line-height: 1.2;
  color: #16211c;
}

/* 60% de la PANTALLA, no de `.container` (pedido del usuario: primero pidió
   70% porque quedaba mucho espacio en blanco a los extremos, después de
   verlo en vivo pidió bajarlo a 60% — se veía "muy ancho") — por eso vive
   FUERA de `.container` (1180px de tope) como hermano directo de
   `.calc-form-section`, que no tiene max-width ni padding horizontal.
   Un `%` (no un `vw` ni un px fijo) es a propósito: bajo el `zoom`
   ambiental de `.uw-wide`, `%` se resuelve contra el padre en el espacio
   ya escalado y crece proporcional sin necesitar ninguna regla `.uw-wide`
   aparte — mismo motivo por el que `#cont-map` usa `width:100%` en vez de
   `100vw` (ver esa sección).
   Padding lateral del diseño: 86px a 1366 (el contenido mide ~636px dentro
   de una tarjeta de ~808px). */
.calc-form {
  width: 60%;
  margin: 0 auto;
  background: #fff;
  padding: clamp(40px, 5vw, 68px) clamp(24px, 6.3vw, 86px) clamp(40px, 4.2vw, 56px);
  box-shadow: 0 20px 50px rgba(8, 56, 32, .12);
}
.calc-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 32px; }
.calc-form__field { margin-bottom: 26px; }
.calc-form__field label,
.calc-form__label {
  display: block;
  margin-bottom: 6px;
  font-size: 14px;
  font-weight: 500;
  color: #16211c;
}
/* Línea inferior únicamente (pedido del usuario con captura: el único
   borde visible en el Figma es el de abajo, tanto en reposo como en
   hover/foco) — mismo criterio "línea inferior" que `.sd-contact`/
   `.cont-form`, solo que acá con `<label>` visible arriba de cada campo.
   El texto va 12px adentro de la línea, como en el diseño. */
.calc-form input[type="text"],
.calc-form input[type="email"],
.calc-form input[type="tel"],
.calc-form select {
  display: block;
  width: 100%;
  box-sizing: border-box;
  border: none;
  border-bottom: 1px solid #d8dcda;
  border-radius: 0;
  background: transparent;
  padding: 10px 12px;
  font-family: var(--font);
  font-size: 14px;
  color: #16211c;
  transition: border-color .2s ease;
}
.calc-form input::placeholder { color: #a3a6a4; }
.calc-form input:hover,
.calc-form select:hover { border-bottom-color: #9a9a9a; }
.calc-form input:focus,
.calc-form select:focus {
  outline: none;
  border-bottom-color: var(--accent);
}

/* Flecha propia en vez de la nativa del navegador (para que se vea igual
   en todos los navegadores) — SVG inline como `background-image` de la
   HOJA DE ESTILOS (self-hosted, no es `style=""` inline: la CSP
   `style-src 'self'` no lo bloquea). Sin elegir (opción vacía, `:invalid`
   por el `required`) se ve gris, como un texto guía. */
.calc-form select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 30px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23555' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 14px;
  cursor: pointer;
}
.calc-form select:invalid { color: #a3a6a4; }
.calc-form select option { color: #16211c; }

/* "Factura estimada actual" / "kWh en tu factura": valor + slider fino (el del
   diseño: línea gris de 2px, tramo verde hasta el punto y un punto verde) y, en
   el de kWh, el enlace "Ver ejemplo" a la derecha. El tramo verde lo dibuja un
   degradado hasta `--pct`, que site.js actualiza en cada movimiento (CSSOM, no
   un `style=""`: la CSP no lo bloquea); Firefox lo pinta solo con
   `::-moz-range-progress`. */
.calc-form__range { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 0; padding-left: 12px; }
/* Ancho mínimo común: los dos sliders arrancan en la misma línea vertical
   ("$100" y "300 kWh" miden distinto). */
.calc-form__range output {
  flex: 0 0 auto;
  box-sizing: border-box;
  min-width: 66px;   /* site.js lo lleva al ancho del valor más largo posible ("$10,000") */
  padding-right: 8px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  color: #444;
}
.calc-form__range input[type="range"] {
  --pct: 20%;
  /* Base chica que crece hasta 350px: si el enlace "Ver ejemplo" no entra al
     lado, la barra se acorta antes de que el enlace baje de línea. */
  flex: 1 1 200px;
  max-width: 350px;
  min-width: 140px;
  height: 18px;
  margin: 0 20px 0 0;
  background: transparent;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
.calc-form__range input[type="range"]::-webkit-slider-runnable-track {
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(to right, var(--accent) 0 var(--pct), #e4e7e5 var(--pct) 100%);
}
.calc-form__range input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 11px;
  height: 11px;
  margin-top: -4.5px;
  border: none;
  border-radius: 50%;
  background: var(--accent);
}
.calc-form__range input[type="range"]::-moz-range-track { height: 2px; border-radius: 2px; background: #e4e7e5; }
.calc-form__range input[type="range"]::-moz-range-progress { height: 2px; border-radius: 2px; background: var(--accent); }
.calc-form__range input[type="range"]::-moz-range-thumb { width: 11px; height: 11px; border: none; border-radius: 50%; background: var(--accent); }
.calc-form__range input[type="range"]:focus { outline: none; }
.calc-form__range input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px rgba(34, 197, 94, .25); }
.calc-form__range input[type="range"]:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 4px rgba(34, 197, 94, .25); }
/* En pantallas táctiles el punto de 11px es difícil de agarrar. */
@media (pointer: coarse) {
  .calc-form__range input[type="range"] { height: 28px; }
  .calc-form__range input[type="range"]::-webkit-slider-thumb { width: 20px; height: 20px; margin-top: -9px; }
  .calc-form__range input[type="range"]::-moz-range-thumb { width: 20px; height: 20px; }
}

/* "Ver ejemplo de kWh en factura »": abre el <dialog> de abajo (ver
   site.js) — mismo criterio visual que `.serv-row__link` ("Ver más"),
   escalado a este contexto más compacto. Va en la misma línea que el
   slider, empujado a la derecha. */
.calc-form__link {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 0 0 2px;
  background: none;
  border: none;
  border-bottom: 1px solid var(--accent);
  font-family: var(--font);
  font-size: 12px;
  font-weight: 600;
  color: var(--accent-ink);
  cursor: pointer;
  transition: color .2s;
}
.calc-form__link:hover { color: var(--brand); }

/* ---- Factura adjunta (rediseño 2026-09-26) ----
   Recuadro verde muy claro: ícono de factura, texto (y la lista de archivos
   elegidos) y el botón, que es el <label> del <input type="file"> oculto. */
.calc-form__adjunto {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 6px 0 28px;
  padding: 22px clamp(18px, 2.2vw, 30px);
  background: #f1f6f3;
}
.calc-form__adjunto-ic { flex: 0 0 auto; width: 32px; height: 32px; color: var(--brand); stroke-width: 1.5; }
.calc-form__adjunto-txt { flex: 1 1 auto; min-width: 0; font-size: 12px; line-height: 1.5; }
.calc-form__adjunto-txt strong { display: block; font-size: 13px; font-weight: 700; color: #16211c; }
.calc-form__adjunto-txt span { color: #8a8f8c; }
.calc-form__archivos { margin: 8px 0 0; padding: 0; list-style: none; color: var(--brand); font-weight: 600; }
.calc-form__archivos li { display: flex; align-items: center; gap: 6px; }
.calc-form__archivos li small { font-weight: 400; color: #8a8f8c; }
.calc-form__archivo-nombre { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Quitar un archivo de la lista (se suman de a uno: 2026-09-27). */
.calc-form__archivo-quitar {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: #8a8f8c;
  font-family: inherit;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.calc-form__archivo-quitar:hover { background: #fdecea; color: #b42318; }
.calc-form__archivo-quitar:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.calc-form__archivos-cupo { margin: 4px 0 0; color: #8a8f8c; }
.calc-form__archivos-error { margin: 8px 0 0; color: #b42318; font-weight: 600; }
/* Oculto a la vista pero no al teclado ni al lector de pantalla. */
.calc-form__file {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.calc-form__adjunto-btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 16px;
  background: #fff;
  border: 1px solid var(--accent);
  font-size: 12.5px;
  font-weight: 600;
  color: #16211c;
  cursor: pointer;
  transition: background-color .2s;
}
.calc-form__adjunto-btn:hover { background: #eef9f2; }
.calc-form__file:focus-visible + .calc-form__adjunto-btn { outline: 2px solid var(--accent); outline-offset: 2px; }
.calc-form__adjunto-btn-ic { width: 16px; height: 16px; }

/* Casilla de aceptación (obligatoria: `required`). */
.calc-form__acepto {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 0 22px;
  padding-left: 16px;
  font-size: 13px;
  line-height: 1.5;
  color: #8a8f8c;
  cursor: pointer;
}
.calc-form__acepto input { flex: 0 0 auto; width: 18px; height: 18px; margin: 0; accent-color: var(--brand); cursor: pointer; }

.calc-form__submit { width: 100%; justify-content: center; font-weight: 700; }

/* ---- Modal "Ver ejemplo del kWh en factura" — <dialog> nativo, centrado
   y con backdrop propios del navegador (nada que reimplementar a mano).
   El centrado (`margin:auto`) se corrigió a nivel sistémico junto al reset
   global (`dialog:modal{margin:auto}`, inicio de este archivo) — no hace
   falta repetirlo acá. */
.calc-dialog { border: none; padding: 0; max-width: min(92vw, 640px); max-height: 85vh; background: transparent; }
.calc-dialog::backdrop { background: rgba(8, 20, 14, .72); }
.calc-dialog__img { display: block; width: 100%; height: auto; max-height: 85vh; object-fit: contain; background: #fff; }
/* `top`/`right` en POSITIVO, no negativo (corregido tras reporte del
   usuario con captura): un offset negativo saca el botón por fuera de la
   propia caja del <dialog> — a ciertos anchos de viewport eso empujaba el
   borde del botón más allá del viewport físico (scroll horizontal de toda
   la página) y además quedaba recortado por el borde del propio diálogo.
   Con un inset positivo el botón queda SIEMPRE dentro de la caja del
   diálogo, flotando sobre la esquina superior derecha de la imagen sin
   escapar nunca de sus límites. */
.calc-dialog__close {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: #fff;
  border: none;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .25);
}
.calc-dialog__close-ic { width: 18px; height: 18px; color: #16211c; }

@media (max-width: 1024px) {
  /* Mismo reset que `.serv-hero__inner`/`.sd-hero__inner`/`.cont-hero__
     inner` (ver esas secciones) — sin esto el hero queda indentado y más
     angosto que el resto del contenido. */
  .calc-hero__inner { margin-left: 0; max-width: 100%; }
  /* 60% de una pantalla angosta deja los campos apretados — se ensancha
     progresivamente a medida que el viewport se achica. */
  .calc-form { width: 84%; }
}
@media (max-width: 640px) {
  .calc-form { width: calc(100% - 48px); padding: 32px 24px; }
  .calc-form__row { grid-template-columns: 1fr; }
  /* Recuadro de la factura: ícono + texto arriba, botón a todo el ancho abajo. */
  .calc-form__adjunto { flex-wrap: wrap; padding: 20px; }
  .calc-form__adjunto-txt { flex-basis: calc(100% - 50px); }
  .calc-form__adjunto-btn { flex-basis: 100%; justify-content: center; }
  /* El slider ocupa la línea; "Ver ejemplo" baja a la siguiente. */
  .calc-form__range input[type="range"] { flex: 1 1 140px; }
  .calc-form__acepto { padding-left: 0; }
}

/* =====================================================================
   ENSANCHADO EN MONITORES ANCHOS (> 1920px) — clase `.uw-wide`

   `ultrawide-zoom.js` agrega `.uw-wide` a <html> SOLO cuando el viewport real
   supera 1920px. No se puede usar una media query aquí: bajo el `zoom` global,
   el viewport de CSS queda "reducido" a ~1920px, así que CSS nunca "ve" el
   ancho real — la clase es el único canal para saberlo. Por eso estas reglas
   NUNCA afectan a móvil ni a <=1920px (la clase no está presente).

   Home ya llena bien la pantalla ancha (secciones `.container-wide` al 95%) y
   NO se toca. Estas páginas (Nosotros, Servicios, Detalle) tienen el contenido
   angosto/indentado por diseño (37–65% del ancho), lo que a 3440px deja
   franjas vacías enormes y se ve desbalanceado; a pedido del usuario se
   ENSANCHA su contenido para que llene el espacio. Los anchos van en px del
   espacio de CSS "reducido" (~1920px), que el zoom luego escala al ancho real.
   ===================================================================== */

/* ---- Nosotros ---- */
/* Intro: se ensancha (centrada como el resto de Nosotros). Se ocultan los
   saltos forzados (.brk) para que el párrafo fluya en el bloque más ancho.
   `.nos-intro__block` es el bloque de ALINEACIÓN — mismo max-width que
   `.nos-distrib__grid` (1440px) para compartir el mismo borde izquierdo (ver
   nota base más arriba); el ancho de ajuste de texto real vive en
   `.nos-intro__inner`. */
.uw-wide .nos-intro__block { max-width: 1440px; margin-inline: auto; }
.uw-wide .nos-intro__inner { max-width: 1280px; }
.uw-wide .nos-intro__text .brk { display: none; }
/* Hero: ver el selector agrupado `.uw-wide .nos-hero__inner, .serv-hero__
   inner, .sd-hero__inner, .cont-hero__inner` más abajo (sección Detalle de
   servicio) — las 4 páginas comparten esta misma regla. */

/* Distribuidor: el bloque se ensancha a 1440px (mismo borde izquierdo que
   `.nos-intro__block`) y el "+N" y los textos crecen. Las marcas van en la
   banda de abajo al mismo ancho; sus logos NO se agrandan (son de baja
   resolución, ~200–242px nativos). Hasta el 2026-09-29 acá también se
   ajustaba el sello, que ya no está. */
.uw-wide .nos-distrib__grid { max-width: 1440px; margin-inline: auto; }
.uw-wide .nos-distrib__title { font-size: 28px; }
.uw-wide .nos-distrib__label { font-size: 22px; }
.uw-wide .nos-distrib__big { font-size: 108px; margin-top: 74px; }
.uw-wide img.nos-distrib__big { height: 96px; }
.uw-wide .nos-distrib__marcas { max-width: 1440px; }

/* Misión/Visión: el texto crece y se ensancha para llenar cada columna, con el
   ícono, la regla y el título también más grandes; se achica el gap entre
   columnas (era 120px) para cerrar el hueco central.

   Corregido 2026-09-13 (aclaración del usuario sobre el pedido de
   "centrado" del mismo día): NO es texto centrado línea por línea — es el
   BLOQUE completo (ícono+título+descripción) el que debe quedar centrado
   como unidad dentro de la columna; el contenido DENTRO del bloque sigue
   alineado a la izquierda (como en base/1920, sin tocar). Antes se había
   centrado cada elemento por separado (`text-align:center` en la tarjeta +
   `margin-inline:auto` en ícono/regla/párrafo cada uno con su propio ancho)
   — eso centraba cada línea de texto individualmente Y desalineaba el
   ícono del título/párrafo entre sí (cada uno centrado a un ancho
   distinto). Ahora `.nos-mv__card` en sí (sin `text-align`, contenido
   left-aligned por defecto) recibe `max-width` (760px, el mismo ancho ya
   usado por el párrafo) + `margin-inline:auto` — esto centra la TARJETA
   como bloque dentro de la columna (que es más ancha, 770px), y todo lo de
   adentro (ícono, título, párrafo) queda alineado entre sí a la izquierda,
   igual que antes. */
/* Corregido 2026-09-13 (mismo día, tercer pedido): el intento anterior
   (1780px) redujo el hueco central pero desalineó el BLOQUE ENTERO de las
   secciones de arriba — el usuario marcó con flechas que "Misión" quedaba
   más a la IZQUIERDA que "Quiénes somos" y que "Visión" se pasaba más a
   la DERECHA que el sello de "Distribuidor autorizado" (1780px es más
   ancho que los 1440px de `.nos-intro__block`/`.nos-distrib__grid`, así
   que al centrarse en el mismo espacio sobresale por ambos lados).
   Fix definitivo: usar el MISMO max-width que esas dos secciones (1440px,
   no 1780px) — al compartir ancho Y método de centrado (`margin-inline:
   auto` dentro del mismo `.container-wide`), los TRES bloques (intro,
   distribuidor, misión/visión) terminan con el mismo borde izquierdo Y
   el mismo borde derecho automáticamente (verificado: los tres en
   235.8px/1675.8px @3440). El `column-gap` se mantiene en 48px (bajado de
   80px en la ronda anterior, sigue vigente — con columnas de ~696px cada
   una a este ancho, sigue sin holgura extra ya que las tarjetas llenan el
   100% de su columna, ver `.nos-mv__card{max-width:none}` abajo). */
.uw-wide .nos-mv__grid { max-width: 1440px; column-gap: 48px; }
/* `width:100%` explícito (no alcanza con `max-width` solo): bajo el zoom
   global de ultra-wide, el ítem de grid NO se estira a la columna por
   default (`justify-items:normal`/stretch) como debería — se queda al
   ancho "shrink-to-fit" de su contenido, probado en vivo incluso forzando
   `justify-self:stretch` explícito, sin efecto. Parece una interacción
   del `zoom` CSS con el cálculo de stretch en este Chromium. `width:100%`
   fuerza el ancho sin depender de ese cálculo. `max-width:none` (antes
   760px): ya no se limita el ancho de la tarjeta — llena su columna
   completa, sin dejar holgura entre Misión y Visión. */
.uw-wide .nos-mv__card { width: 100%; max-width: none; }
.uw-wide .nos-mv__text { max-width: none; font-size: 21px; }
.uw-wide .nos-mv__title { font-size: 34px; }
.uw-wide .nos-mv__icon { width: 108px; }
.uw-wide .nos-mv__rule { width: 180px; }

/* ---- Servicios ---- */
/* Fila de servicio: llena ~85% y la foto cuadrada (fija en 289px) crece a
   460px para no quedar chica entre columnas de texto más anchas. */
/* Corregido (2026-09-13, pedido del usuario con captura anotada): con las 2
   columnas de texto en `1fr 1fr` a este ancho (1640px), la columna del
   TÍTULO quedaba de 502px, pero el título real (p. ej. "Ingeniería y
   Diseño") mide solo ~225px — dejaba ~277px de aire en blanco ANTES del gap
   de diseño de 48px, un salto visual enorme entre el texto y la foto
   (marcado en la captura). Se cambió la 1ª columna a un ancho FIJO 360px
   (cabe en una línea casi cualquier título real, medido con
   `canvas.measureText` en la fuente/peso reales — el más largo,
   "Diagnóstico y Readecuación de Plantas Solares" ~550px, sigue partiéndose
   en 2 líneas, igual que ya hace a 1050px/@1920, no es una regresión).
   El GAP de diseño (48px, medido de ACTUAL) no se tocó — el problema era el
   ancho de columna, no el gap en sí.

   Segunda vuelta, mismo día: el usuario NO quiso que la descripción creciera
   al ancho liberado (`1fr`≈724px, resultado de la corrección anterior) — pidió
   devolverla a su ancho previo (502px, el de la ronda "ensanchar" original,
   con columnas `1fr 460px 1fr`) manteniendo la reducción del título. Con las
   3 columnas ahora en px fijo (360/460/502), el `max-width` del grid se ajustó
   a la suma exacta (360+48+460+48+502=1418) para que la fila no quede con
   espacio vacío de sobra a la derecha (un grid con columnas fijas más angosto
   que su `max-width` deja hueco al final si no se iguala el `max-width` a la
   suma real de columnas+gaps — ver mismo patrón ya usado para
   `.container-detail`/`.uw-wide` en otras secciones).

   BUG real (encontrado y corregido 2026-09-16, reportado por el usuario con
   captura: la descripción se desbordaba del recuadro verde de hover en
   resoluciones >1920px): el cálculo de arriba (1418 = suma de columnas+gaps)
   NO contaba el propio `padding:20px 40px` de `.serv-row__grid` (heredado de
   la regla base). Con `box-sizing:border-box`, `max-width` fija el ancho del
   BORDER-BOX (contenido + padding) — así que el contenido real disponible
   para las 3 columnas quedaba en 1418-80(padding)=1338px, 80px MENOS de lo
   que las columnas fijas (1418px) necesitaban. CSS Grid no encoge columnas
   con ancho fijo en px: en vez de eso, deja que la REJILLA ENTERA se
   desborde de su propio contenedor — confirmado en vivo
   (`grid.scrollWidth(1458) > grid.clientWidth(1418)`, sin exagerar a ojo).
   El fondo verde de `:hover` se pinta sobre el border-box (1418px, el
   tamaño "declarado"), pero la 3ª columna (texto) se renderiza más allá de
   ese borde — de ahí el texto "flotando" fuera del recuadro verde.
   Fix: `max-width` pasa a 1498px (1418 + 80 de padding), para que el
   border-box tenga espacio real para columnas+gaps+padding. OJO: esto
   ensancha la fila ~40px por lado (queda centrada con `margin-inline:auto`),
   así que el margen del hero (`.uw-wide ... margin-left:241.9px` más abajo)
   tuvo que re-medirse en el mismo cambio — ver esa nota. */
.uw-wide .serv-row__grid { max-width: 1498px; grid-template-columns: 360px 460px 502px; }
/* Descripción más grande (pedido del usuario, subido de 19 a 20px en la
   segunda vuelta) — de 16px (tope del clamp base) a 20px. */
.uw-wide .serv-row__text { font-size: 20px; }
/* Permisos: encabezado + rejilla de 6 pasos llenan ~90%. */
.uw-wide .serv-permisos__head { max-width: 1680px; }
.uw-wide .serv-permisos__grid { max-width: 1680px; }
/* Hero (2026-09-13, corregido, DOS veces el mismo día): el título "Nuestros
   Servicios" quedaba desalineado del título de cada tarjeta de servicio
   ("Ingeniería y Diseño", etc.) — el hero usa `margin-left:12%` (relativo al
   ancho de SU `.container-wide`, 1821.7px medidos), mientras que el título de
   tarjeta está en el borde izquierdo de `.serv-row__grid` (que tiene su
   PROPIO max-width/centrado, distinto del de `.container-wide`) — dos
   fórmulas de posicionamiento distintas que no coinciden por accidente,
   marcado por el usuario con una flecha en captura. Se fija el margen del
   hero a un valor en px (medido en vivo para que ambos títulos compartan
   exactamente el mismo borde izquierdo) en vez de heredar el 12% base — solo
   en ultra-wide, la regla base (12%) sigue igual en `<=1920px`.
   OJO: el valor en px DEPENDE del `max-width` de `.serv-row__grid` (cambiarlo
   desplaza dónde cae el borde izquierdo de la fila) — se calibró primero en
   175.8px con el ancho de fila de 1640px, y hubo que RE-MEDIR y subir a
   241.9px (el valor vigente) tras achicar `.serv-row__grid` a 1418px en la
   corrección de abajo. Si se vuelve a tocar ese ancho, recalcular este valor
   en el mismo cambio o el hero se desalinea de nuevo. */
/* ---- Detalle de servicio ---- */
/* Todo el cuerpo (grilla foto/frase | texto/otros | tarjetas | banner | FAQ)
   llena ~90% en vez de 65%. */
.uw-wide .container-detail { max-width: 1720px; }

/* Hero — mismo override EXACTO para las 5 páginas con hero (Nosotros,
   Servicios, Detalle, Contáctanos, Calculadora): copian la posición de
   Servicios, no la de su propio cuerpo. Un solo selector agrupado (code
   review 2026-09-15: antes eran 3 reglas idénticas copiadas a mano, y a
   `.cont-hero__inner` directamente le faltaba esta — con un selector
   agrupado no puede volver a faltarle a una sin que se note en el diff;
   `.calc-hero__inner` se sumó al mismo grupo 2026-09-22 por el mismo
   motivo). */
.uw-wide .nos-hero__inner,
.uw-wide .serv-hero__inner,
.uw-wide .sd-hero__inner,
.uw-wide .cont-hero__inner,
.uw-wide .calc-hero__inner,
.uw-wide .shop-hero__inner {
  max-width: 900px;
  /* 201.9px (2026-09-16, re-medido tras el fix de `.serv-row__grid` de
     arriba — el max-width de esa fila pasó de 1418 a 1498px, lo que la
     ensancha ~40px por lado al recentrarse y corre el borde izquierdo del
     título de tarjeta 40px hacia la izquierda; era 241.9px). */
  margin-left: 201.9px;
}

/* =====================================================================
   TIENDA — catálogo, ficha, carrito y "Enviar pedido"
   Diseño: "Online store_Indasa_website.pdf" (4 pantallas de 1821px de
   ancho). Los clamp() llegan a la medida del diseño cerca de ese ancho y
   se achican con el viewport, como el resto del sitio.
   ===================================================================== */
:root {
  --shop-green: #61de82;     /* "Agregar al carrito" de la tarjeta y WhatsApp */
  --shop-green-h: #4ccb6e;
  --shop-dark: #133b27;      /* modelo, títulos y botón oscuro */
  --shop-dark-h: #0b2819;
  --shop-line: #e6e6e6;      /* borde del selector de cantidad */
  --shop-row: #f1f1f1;       /* filas alternas de la ficha técnica */
  --shop-group: #e5ece6;     /* fila de grupo de la ficha técnica */
}

.shop-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.shop-ic { width: 1.25em; height: 1.25em; flex-shrink: 0; }
.shop-link { color: var(--accent-ink); font-weight: 600; }
.shop-link:hover { color: var(--shop-dark); }
.shop__container { width: 100%; max-width: 1320px; margin-inline: auto; padding-inline: 24px; }

/* ---- Header: submenú de categorías ---- */
.site-nav .has-sub { position: relative; display: flex; align-items: center; gap: 6px; }
.site-nav ul a.is-current { color: var(--accent); }
.site-subnav__toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0; border: 0; background: transparent;
  color: #eef4f0; cursor: pointer;
}
.site-subnav__toggle:hover { color: var(--accent); }
.site-subnav__toggle svg { width: 14px; height: 14px; transition: transform .2s ease; }
.has-sub.is-open > .site-subnav__toggle svg { transform: rotate(180deg); }
.site-nav ul.site-subnav { display: block; list-style: none; }
.site-nav .site-subnav a { display: block; padding: 10px 24px; font-size: 14px; white-space: nowrap; }

@media (min-width: 901px) {
  .site-nav ul.site-subnav {
    position: absolute; top: calc(100% + 26px); left: 50%; z-index: 1100;
    min-width: 290px; padding: 10px 0;
    background: var(--brand); border-top: 3px solid var(--accent);
    box-shadow: 0 18px 40px rgba(0, 0, 0, .28);
    opacity: 0; visibility: hidden; transform: translate(-50%, 8px);
    transition: opacity .2s ease, transform .2s ease, visibility .2s;
  }
  /* Puente invisible sobre el hueco entre el enlace y el menú: sin él, el
     hover se corta en el camino y el menú se cierra antes de llegar. */
  .site-nav ul.site-subnav::before { content: ""; position: absolute; left: 0; right: 0; top: -29px; height: 29px; }
  .has-sub:hover > .site-subnav,
  .has-sub:focus-within > .site-subnav,
  .has-sub.is-open > .site-subnav { opacity: 1; visibility: visible; transform: translate(-50%, 0); }
  .site-nav .site-subnav a:hover { background: rgba(255, 255, 255, .06); }
}
@media (max-width: 900px) {
  .site-nav .has-sub { flex-wrap: wrap; }
  .site-nav ul.site-subnav {
    display: none; flex-basis: 100%;
    margin-top: 10px; padding-left: 16px;
    border-left: 2px solid rgba(255, 255, 255, .18);
  }
  .site-nav .has-sub.is-open > .site-subnav { display: block; }
  .site-nav .site-subnav a { padding: 8px 0; white-space: normal; }
}

/* ---- Header: carrito ---- */
.nav-cart { position: relative; }
.nav-cart__count {
  position: absolute; top: -7px; right: -9px;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
  background: var(--shop-green); color: var(--shop-dark);
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
}
.nav-cart__count[hidden] { display: none; }
/* En móvil el menú se pliega: el carrito queda afuera, junto al botón. */
.nav-cart--mobile { display: none; }
@media (max-width: 900px) {
  .nav-cart--mobile { display: inline-flex; margin-left: auto; }
  .site-nav .nav-cart { display: none; }
}

/* ---- Migas de pan ---- */
.shop-crumbs { background: #fff; border-bottom: 1px solid var(--shop-line); }
.shop-crumbs__list {
  display: flex; flex-wrap: wrap; align-items: center;
  list-style: none; padding-block: 14px;
  font-size: 13px; color: var(--ink-soft);
}
.shop-crumbs__item a { color: var(--ink-soft); }
.shop-crumbs__item a:hover { color: var(--accent-ink); }
.shop-crumbs__item span[aria-current] { color: var(--shop-dark); font-weight: 600; }
.shop-crumbs__sep { margin: 0 8px; color: var(--shop-line); }
/* La última miga (la página actual) puede ser larga —el modelo de un
   producto— y no tiene a dónde más achicarse en el teléfono. */
.shop-crumbs__item:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }

/* ---- Buscador de productos (portada, categoría y resultados) ---- */
/* Solo padding arriba: lo que sigue (shop-cats o shop) ya trae su propio
   espacio arriba y no hace falta duplicarlo. */
.shop-search-band { background: #fff; padding: clamp(20px, 2.4vw, 32px) 0 0; }
.shop-search {
  display: flex; align-items: stretch; width: 100%; max-width: 520px;
  border: 2px solid var(--shop-line); transition: border-color .15s ease;
}
.shop-search:focus-within { border-color: var(--shop-green); }
.shop-search input {
  flex: 1; min-width: 0; border: 0; padding: 12px 14px; background: transparent;
  font-family: var(--font); font-size: 15px; color: var(--ink);
}
.shop-search input::placeholder { color: #9a9a9a; }
.shop-search input:focus { outline: none; }
/* Safari agrega una "x" propia al buscador (type="search"); la del
   diseño ya alcanza con la lupa del botón. */
.shop-search input::-webkit-search-cancel-button { -webkit-appearance: none; }
.shop-search button {
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  width: 48px; border: 0; background: var(--shop-dark); color: #fff; cursor: pointer;
  transition: background .15s ease;
}
.shop-search button:hover { background: var(--shop-dark-h); }
.shop-search button .shop-ic { width: 19px; height: 19px; }

/* ---- Encabezado (las 6 pantallas) ---- */
/* Mismo hero que Nosotros/Servicios/Detalle/Contáctanos/Calculadora
   (2026-09-23, pedido del usuario: el del catálogo se veía distinto — otra
   sangría a la izquierda, otro tamaño de letra y un espacio desparejo bajo
   la línea verde). Antes tenía medidas propias sacadas del PDF de la
   tienda (título de 18-24px, sangría del 18,75% de la PANTALLA, subtítulo
   con su propio margen); ahora usa lo mismo que las demás, una sola vez:
   - título/línea/subtítulo: los selectores agrupados de la sección
     Nosotros (`.nos-hero__title` y compañía, más arriba);
   - posición: `.container-wide` por fuera (ver partials/tienda-hero.php) +
     `margin-left:12%` / `max-width:640px` por dentro, con el mismo
     override de ultra-wide (`.uw-wide .shop-hero__inner`, más abajo) y el
     mismo reset en angosto;
   - alto y arranque: `padding:70px 0 56px` y `min-height:300px`, igual que
     `.nos-hero`, para que el título caiga a la misma altura.
   Lo único propio de la tienda es el fondo: la foto con el tinte verde. */
.shop-hero {
  position: relative; isolation: isolate; overflow: hidden;
  min-height: 300px; padding: 70px 0 56px;
  background: var(--hero-bg); color: #fff; text-align: left;
}
.shop-hero__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; }
/* Tinte del diseño: verde oscuro arriba, gris verdoso abajo. */
.shop-hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(8, 48, 28, .94) 0%, rgba(12, 58, 36, .80) 42%, rgba(44, 92, 88, .62) 100%);
}
.shop-hero__inner { margin-left: 12%; max-width: 640px; color: #fff; }
/* Mismo reset que `.nos-hero__inner`/`.serv-hero__inner` (a 1024px): sin él
   el 12% + 640px dejan el texto indentado y angosto en tablet/celular. */
@media (max-width: 1024px) { .shop-hero__inner { margin-left: 0; max-width: 100%; } }

/* ---- Botones y selector de cantidad ---- */
/* Tamaño fijo, proporcional al resto de la página (referencia: botones de
   compra de La Curacao, 49px de alto y texto de 14px). Antes crecían con el
   ancho de la pantalla y en monitores grandes quedaban enormes. */
.shop-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 10px 22px;
  border: 0; border-radius: 0; cursor: pointer; text-align: center;
  font-family: var(--font); font-size: 15px; font-weight: 700; color: #fff;
  transition: background .15s ease, opacity .15s ease;
}
.shop-btn--dark { background: var(--shop-dark); }
.shop-btn--dark:hover { background: var(--shop-dark-h); }
.shop-btn--green { background: var(--shop-green); }
.shop-btn--green:hover { background: var(--shop-green-h); }
.shop-btn:disabled, .shop-btn.is-disabled { opacity: .45; cursor: not-allowed; }
.shop-btn.is-sending { opacity: .7; cursor: progress; }
.shop-btn .shop-ic { width: 20px; height: 20px; }

.shop-qty { display: flex; align-items: stretch; height: 48px; border: 2px solid var(--shop-line); background: #fff; }
.shop-qty__btn {
  flex: 0 0 48px; display: flex; align-items: center; justify-content: center;
  border: 0; background: transparent; cursor: pointer;
  font-family: var(--font); font-size: 20px; font-weight: 600; color: var(--shop-dark);
}
.shop-qty__btn:hover { background: #f7f7f7; color: var(--accent-ink); }
.shop-qty__input {
  flex: 1; width: 100%; min-width: 0; border: 0; background: transparent; text-align: center;
  font-family: var(--font); font-size: 17px; font-weight: 600; color: var(--shop-dark);
  -moz-appearance: textfield; appearance: textfield;
}
.shop-qty__input::-webkit-outer-spin-button,
.shop-qty__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.shop-qty__input:focus { outline: 2px solid var(--shop-green); outline-offset: -2px; }
.shop-qty--sm { height: 38px; max-width: 322px; }
.shop-qty--sm .shop-qty__btn { flex-basis: 40px; font-size: 18px; }
.shop-qty--sm .shop-qty__input { font-size: 15px; }

/* ---- Pantalla 1: grilla ---- */
.shop { background: #fff; padding: clamp(40px, 6vw, 110px) 0 clamp(60px, 7vw, 130px); }

.shop-toolbar {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px 24px;
  max-width: 1220px; margin: 0 auto clamp(32px, 4vw, 70px);
  padding-bottom: 16px; border-bottom: 1px solid var(--line);
  font-size: 15px; color: var(--ink-soft);
}
.shop-toolbar__info strong { font-weight: 600; color: var(--shop-dark); }
.shop-toolbar__form { display: flex; align-items: center; gap: 10px; }
.shop-toolbar__form select {
  appearance: none; -webkit-appearance: none;
  padding: 8px 36px 8px 14px; border: 2px solid var(--shop-line); border-radius: 0;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23133b27' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 12px center / 12px;
  font-family: var(--font); font-size: 15px; font-weight: 600; color: var(--shop-dark); cursor: pointer;
}
.shop-toolbar__form select:focus { outline: 2px solid var(--shop-green); outline-offset: 1px; }
.shop-toolbar__apply { padding: 8px 14px; border: 0; background: var(--shop-dark); color: #fff; font-family: var(--font); cursor: pointer; }

.shop-grid {
  list-style: none; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: clamp(24px, 4vw, 80px); row-gap: clamp(48px, 5.5vw, 100px);
  max-width: 1220px; margin-inline: auto;
}
.shop-card { display: flex; flex-direction: column; align-items: center; text-align: center; }
.shop-card__media { position: relative; width: 100%; max-width: 300px; }
.shop-card__img { display: flex; align-items: center; justify-content: center; width: 100%; aspect-ratio: 1 / 1; }
.shop-card__img img { width: 100%; height: 100%; object-fit: contain; transition: transform .35s ease; }
.shop-card:hover .shop-card__img img { transform: scale(1.03); }
.shop-card__placeholder,
.shop-product__placeholder {
  display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;
  background: var(--page); color: #c3cbc5; font-size: 56px;
}
.shop-card__add {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  /* Esquinas de arriba redondeadas y las de abajo rectas, como el diseño. */
  padding: 14px 16px; border: 0; border-radius: 18px 18px 0 0; cursor: pointer;
  background: var(--shop-green); color: #fff;
  font-family: var(--font); font-size: 15px; font-weight: 700;
  opacity: 0; transform: translateY(10px);
  transition: opacity .25s ease, transform .25s ease, background .15s ease;
}
.shop-card:hover .shop-card__add,
.shop-card:focus-within .shop-card__add { opacity: 1; transform: none; }
.shop-card__add:hover { background: var(--shop-green-h); }
/* Pantallas táctiles: sin hover el botón quedaría escondido para siempre.
   Suelto bajo la foto un <button> no se estira al ancho de la tarjeta:
   los márgenes automáticos lo centran. */
@media (hover: none) {
  .shop-card__add { position: static; margin: 12px auto 0; opacity: 1; transform: none; }
}
.shop-card__body { display: flex; flex-direction: column; align-items: center; gap: 6px; margin-top: clamp(16px, 2.2vw, 40px); }
.shop-card__name { font-size: clamp(14px, .95vw, 17px); color: var(--ink); }
.shop-card__model { font-size: clamp(20px, 1.6vw, 30px); font-weight: 700; line-height: 1.2; color: var(--shop-dark); transition: color .15s ease; }
.shop-card__body:hover .shop-card__model { color: var(--accent-ink); }
.shop-card__price { font-size: 16px; font-weight: 600; color: var(--accent-ink); }

.shop-empty { padding: 60px 0; text-align: center; color: var(--ink-soft); }
.shop-empty p { margin-bottom: 14px; }

.shop-pager { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 8px; margin-top: clamp(48px, 5vw, 90px); }
.shop-pager__link {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; height: 44px; padding: 0 14px;
  border: 2px solid var(--shop-line); font-size: 15px; font-weight: 600; color: var(--shop-dark);
  transition: border-color .15s ease;
}
a.shop-pager__link:hover { border-color: var(--shop-green); }
.shop-pager__link.is-active { background: var(--shop-dark); border-color: var(--shop-dark); color: #fff; }
.shop-pager__link.is-off { opacity: .4; }
.shop-pager__gap { padding: 0 4px; color: var(--muted); }

@media (max-width: 1024px) { .shop-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) {
  .shop-grid { grid-template-columns: 1fr; }
  .shop-pager__num, .shop-pager__gap { display: none; }
}

/* ---- Pantalla 2: ficha del producto ---- */
.shop-product { background: #fff; padding: clamp(40px, 6.5vw, 120px) 0 clamp(40px, 5vw, 90px); }
.shop-product__grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center; gap: clamp(32px, 5vw, 100px); max-width: 1260px;
}
.shop-product__media { display: flex; justify-content: center; }
.shop-product__media img { width: 100%; max-width: 560px; aspect-ratio: 1 / 1; object-fit: contain; }
.shop-product__placeholder { max-width: 560px; aspect-ratio: 1 / 1; font-size: 90px; }
/* Título del modelo cerca del de la referencia (La Curacao: 24px). */
.shop-product__name { font-size: clamp(15px, 1.1vw, 18px); font-weight: 300; color: var(--ink); }
.shop-product__model { margin-top: 4px; font-size: clamp(22px, 1.8vw, 28px); font-weight: 700; line-height: 1.2; color: var(--shop-dark); }
.shop-product__price { margin-top: 8px; font-size: 20px; font-weight: 600; color: var(--accent-ink); }
.shop-product__desc { margin-top: 16px; line-height: 1.7; color: var(--ink-soft); white-space: pre-line; }
.shop-product__buy { max-width: 520px; margin-top: clamp(22px, 2vw, 32px); }
.shop-product__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 16px; }
@media (max-width: 900px) {
  .shop-product__grid { grid-template-columns: 1fr; }
  .shop-product__media img, .shop-product__placeholder { max-width: 420px; }
}
@media (max-width: 480px) { .shop-product__actions { grid-template-columns: 1fr; } }

.shop-specs { background: #fff; padding: clamp(20px, 3vw, 60px) 0 clamp(70px, 7vw, 140px); }
.shop-specs__wrap { max-width: 1160px; margin-inline: auto; overflow-x: auto; }
.shop-specs__table { width: 100%; border-collapse: collapse; font-size: clamp(14px, 1vw, 18px); color: #111; }
.shop-specs__table thead th {
  padding: 0 16px 12px; border-bottom: 4px solid var(--shop-dark); text-align: left;
  font-size: clamp(16px, 1.2vw, 20px); font-weight: 700; color: var(--shop-dark);
}
.shop-specs__table thead th:first-child { padding-left: 12px; }
.shop-specs__table thead th span { display: inline-block; padding-left: 9px; border-left: 3px solid var(--shop-green); line-height: 1; }
.shop-specs__table tbody th,
.shop-specs__table tbody td { padding: 15px 16px; text-align: left; vertical-align: top; }
.shop-specs__table tbody th { width: 66%; padding-left: clamp(20px, 3.4vw, 60px); font-weight: 400; }
.shop-specs__table tbody td { font-weight: 600; }
.shop-specs__table .shop-specs__group th { background: var(--shop-group); font-weight: 700; }
.shop-specs__table tbody tr:nth-child(odd):not(.shop-specs__group) { background: var(--shop-row); }
@media (max-width: 640px) { .shop-specs__table tbody th { width: 55%; } }

/* ---- Pantalla 3: carrito ---- */
html.has-cart-open, html.has-cart-open body { overflow: hidden; }
.cart { position: fixed; inset: 0; z-index: 10000; visibility: hidden; transition: visibility 0s linear .35s; }
.cart.is-open { visibility: visible; transition-delay: 0s; }
.cart__backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .42); opacity: 0; transition: opacity .35s ease; }
.cart.is-open .cart__backdrop { opacity: 1; }
.cart__panel {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(650px, 100%);
  display: flex; flex-direction: column;
  padding: clamp(24px, 3.2vw, 58px) clamp(20px, 3.2vw, 58px) clamp(24px, 2.6vw, 48px);
  background: #fff; box-shadow: -20px 0 50px rgba(0, 0, 0, .15);
  transform: translateX(100%); transition: transform .35s cubic-bezier(.4, 0, .2, 1);
}
.cart.is-open .cart__panel { transform: none; }
.cart__close {
  position: absolute; top: clamp(14px, 2vw, 34px); right: clamp(14px, 2vw, 40px);
  display: flex; align-items: center; justify-content: center; width: 48px; height: 48px;
  border: 0; background: transparent; color: #666; cursor: pointer;
}
.cart__close:hover { color: var(--shop-dark); }
.cart__close .shop-ic { width: 34px; height: 34px; }
.cart__title {
  margin-top: clamp(40px, 4vw, 70px); padding-bottom: 28px; border-bottom: 1px solid #e2e2e2;
  font-size: clamp(24px, 1.9vw, 34px); font-weight: 700; text-transform: uppercase; color: var(--shop-dark);
}
.cart__body {
  flex: 1; min-height: 0; overflow-y: auto; margin-right: -12px; padding-right: 12px;
  border-bottom: 1px solid #e2e2e2; scrollbar-width: thin; scrollbar-color: #bdbdbd transparent;
}
.cart__list { list-style: none; padding: 14px 0; }
.cart-item { display: flex; align-items: center; gap: clamp(16px, 1.8vw, 32px); padding: 16px 0; }
.cart-item__thumb,
.summary-item__thumb { display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.cart-item__thumb { width: clamp(80px, 6vw, 110px); height: clamp(80px, 6vw, 110px); }
.cart-item__thumb img,
.summary-item__thumb img { width: 100%; height: 100%; object-fit: contain; }
.cart-item__thumb.is-empty,
.summary-item__thumb.is-empty { background: var(--page); }
.cart-item__info { flex: 1; min-width: 0; }
.cart-item__name { display: block; font-size: 15px; color: var(--ink); }
.cart-item__model { display: block; margin-bottom: 12px; font-size: clamp(18px, 1.35vw, 24px); font-weight: 700; line-height: 1.25; color: var(--shop-dark); }
a.cart-item__model:hover { color: var(--accent-ink); }
.cart__empty { padding: 36px 0; color: var(--ink-soft); }
.cart__empty[hidden], .cart__note[hidden] { display: none; }
.cart__note { padding-bottom: 16px; font-size: 14px; color: #8a5a00; }
.cart__foot { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; padding-top: clamp(24px, 3vw, 58px); }
.cart__foot--solo { grid-template-columns: 1fr; }
.cart__foot .shop-btn { padding-inline: 12px; }
@media (max-width: 480px) { .cart__foot { grid-template-columns: 1fr; } }

/* ---- Pantalla 4: "Enviar pedido" ---- */
.shop-order { background: #fff; padding: clamp(40px, 6.5vw, 120px) 0 clamp(60px, 7vw, 130px); }
.shop-order__grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 390px);
  align-items: start; gap: clamp(40px, 5.5vw, 90px); max-width: 1270px;
}
.shop-order__title,
.shop-summary__title { font-size: clamp(24px, 1.8vw, 32px); font-weight: 700; color: var(--shop-dark); }
.shop-alert { margin-top: 18px; padding: 12px 16px; border-left: 4px solid #d93025; background: #fdecea; font-size: 15px; color: #8a1c12; }
.shop-field { margin-top: clamp(18px, 1.6vw, 30px); }
.shop-field input,
.shop-field select {
  width: 100%; padding: 14px 12px; border: 0; border-bottom: 2px solid #b9b9b9; border-radius: 0; background: transparent;
  font-family: var(--font); font-size: clamp(16px, 1.4vw, 26px); font-weight: 300; color: var(--ink);
}
.shop-field input::placeholder { color: #b7b7b7; }
.shop-field select {
  appearance: none; -webkit-appearance: none; padding-right: 44px; cursor: pointer;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239a9a9a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 10px center / 22px;
}
/* Mientras no se elige departamento, el texto se ve como los placeholders. */
.shop-field select:invalid { color: #b7b7b7; }
.shop-field select option { color: var(--ink); }
.shop-field input:focus,
.shop-field select:focus { outline: none; border-bottom-color: var(--shop-green); }
.shop-field.has-error input,
.shop-field.has-error select { border-bottom-color: #d93025; }
.shop-field__error { margin-top: 6px; font-size: 14px; color: #b42318; }
.shop-field[hidden] { display: none; }
.shop-order__submit { min-width: 258px; margin-top: clamp(36px, 3.6vw, 66px); }
.shop-hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }

.shop-summary__title { padding-bottom: 20px; border-bottom: 1px solid #d9d9d9; }
.shop-summary__list {
  list-style: none; max-height: 560px; overflow-y: auto; padding: 16px 14px 16px 0;
  border-bottom: 1px solid #d9d9d9; scrollbar-width: thin; scrollbar-color: #bdbdbd transparent;
}
.shop-summary__list:empty { display: none; }
.summary-item { display: flex; align-items: center; gap: 22px; padding: 14px 0; }
.summary-item__thumb { width: 84px; height: 84px; }
.summary-item__info { min-width: 0; }
.summary-item__name { display: block; font-size: 13px; color: var(--ink); }
.summary-item__model { display: block; font-size: 18px; font-weight: 700; line-height: 1.25; color: var(--shop-dark); }
.summary-item__qty { display: block; margin-top: 2px; font-size: 13px; color: var(--muted); }
.shop-summary__empty { padding: 24px 0; color: var(--ink-soft); }
@media (max-width: 900px) { .shop-order__grid { grid-template-columns: 1fr; } }

/* ---- Confirmación del pedido ---- */
.shop-thanks { background: #fff; padding: clamp(50px, 6vw, 110px) 0; text-align: center; }
.shop-thanks__inner { max-width: 640px; }
.shop-thanks__num { font-size: 15px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--accent-ink); }
.shop-thanks__text { margin: 14px 0 34px; font-size: clamp(17px, 1.3vw, 22px); line-height: 1.6; color: var(--ink-soft); }

/* ---- Portada del catálogo (prototipo de Figma "Catálogo de productos") ----
   Tarjetas de a dos. Las líneas verticales y el gris de la banda final del
   prototipo se quitaron (fondo blanco) y los espacios se compactaron. */
.shop-cats { background: #fff; padding: clamp(32px, 3.5vw, 56px) 0 clamp(40px, 4vw, 64px); }
.shop-cats__inner { width: 100%; max-width: 1254px; margin-inline: auto; padding-inline: 24px; }
.shop-cats__grid {
  --gap: clamp(24px, 3.4vw, 48px);
  list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--gap); row-gap: clamp(32px, 3.4vw, 48px);
}
/* La última, si queda sola en su fila, va al centro con el mismo ancho. */
.shop-cats__grid > li:last-child:nth-child(odd) {
  grid-column: 1 / -1; justify-self: center; width: calc((100% - var(--gap)) / 2);
}

.shop-cat { display: block; }
.shop-cat:focus-visible { outline: 3px solid var(--accent); outline-offset: 6px; }
.shop-cat__media { display: block; aspect-ratio: 755 / 484; overflow: hidden; background: var(--page); }
.shop-cat__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.shop-cat:hover .shop-cat__media img { transform: scale(1.04); }
.shop-cat__placeholder { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; font-size: 64px; color: #c3cbc5; }
/* "Ver productos" sobre el borde inferior de la foto, con el estilo del
   "Agregar al carrito" de las tarjetas de producto (mismo alto, verde y
   esquinas de arriba redondeadas). Aparece al pasar el mouse; en pantallas
   táctiles, que no tienen hover, queda siempre visible. */
.shop-cat__media { position: relative; }
.shop-cat__ver {
  position: absolute; left: 50%; bottom: 0; z-index: 1;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: min(300px, 72%); padding: 14px 16px;
  border-radius: 18px 18px 0 0; background: var(--shop-green); color: #fff;
  font-size: 15px; font-weight: 700; white-space: nowrap;
  opacity: 0; transform: translate(-50%, 10px);
  transition: opacity .25s ease, transform .25s ease, background .15s ease;
}
.shop-cat:hover .shop-cat__ver,
.shop-cat:focus-visible .shop-cat__ver { opacity: 1; transform: translate(-50%, 0); }
.shop-cat__ver:hover { background: var(--shop-green-h); }
@media (hover: none) {
  .shop-cat__ver { opacity: 1; transform: translate(-50%, 0); }
}
.shop-cat__name { margin-top: clamp(12px, 1.2vw, 18px); font-size: clamp(16px, 1.25vw, 19px); font-weight: 700; line-height: 1.3; color: var(--shop-dark); }
.shop-cat__sep {
  display: block; width: clamp(80px, 8vw, 120px); height: 5px;
  margin-top: clamp(10px, 1vw, 14px); background: var(--accent); transition: width .3s ease;
}
.shop-cat:hover .shop-cat__sep { width: clamp(120px, 12.5vw, 190px); }
.shop-cat__text { margin-top: 10px; font-size: clamp(17px, 1.5vw, 22px); font-weight: 300; line-height: 1.35; color: #26302a; }

.shop-band { background: #fff; padding: clamp(36px, 4vw, 60px) 24px; text-align: center; }
.shop-band__inner { max-width: 1000px; margin-inline: auto; }
.shop-band__text { font-size: clamp(16px, 1.2vw, 18px); font-weight: 700; line-height: 1.6; color: var(--shop-dark); }
/* La palabra destacada sigue la frase en la misma línea, sin salto aparte. */
.shop-band__accent { color: var(--accent); }
/* Mismo tamaño que los demás botones de la tienda. */
.shop-band__btn {
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; gap: 10px;
  margin-top: clamp(18px, 2vw, 26px); min-height: 48px; padding: 12px 30px;
  background: var(--accent); color: #fff;
  font-size: 15px; font-weight: 700;
  transition: background .15s ease;
}
.shop-band__btn:hover { background: var(--accent-h); }
/* Esquina con triángulo más claro, como el botón del prototipo. */
.shop-band__btn::after {
  content: ""; position: absolute; right: 0; bottom: 0; width: 0; height: 0;
  border-style: solid; border-width: 0 0 18px 18px;
  border-color: transparent transparent #4ff09a transparent;
}

/* Logos de marcas bajo el botón, en gris como el prototipo; toman su
   color al pasar el mouse.
   - Caja fija con object-fit: los logos subidos no tienen la misma
     proporción ni el mismo margen interno, y así ocupan lo mismo.
   - multiply: los que vienen con fondo blanco (no transparente) dejan de
     verse como recuadros sobre el gris de la banda. */
/* Logos de marcas de la banda final: SIN USO desde el 2026-09-30 (se quitaron
   del catálogo "por ahora", a pedido del usuario). Se dejan por si vuelven. */
.shop-band__marcas {
  list-style: none; display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: clamp(16px, 2.4vw, 36px) clamp(24px, 3.4vw, 50px);
  max-width: 1160px; margin: clamp(24px, 3vw, 40px) auto 0;
}
.shop-band__marca img {
  width: clamp(130px, 13vw, 190px); height: clamp(52px, 5.6vw, 84px);
  object-fit: contain; mix-blend-mode: multiply;
  filter: grayscale(1); opacity: .6;
  transition: filter .25s ease, opacity .25s ease;
}
.shop-band__marca img:hover { filter: none; opacity: 1; }

@media (max-width: 700px) {
  .shop-cats__grid { grid-template-columns: 1fr; }
  .shop-cats__grid > li:last-child:nth-child(odd) { width: 100%; }
  /* En el teléfono la tarjeta ya es angosta: el botón queda apretado y
     sobra, porque tocar la foto lleva a la categoría igual. */
  .shop-cat__ver { display: none; }
}

/* =====================================================================
   FORMULARIOS PÚBLICOS — lo común (2026-09-27, envío por correo; ver
   FormularioPublico en app/Support)
   ===================================================================== */
/* Campo trampa: la persona no lo ve ni llega con el teclado; un robot que
   llena todos los campos lo completa y el envío se descarta. */
.campo-trampa { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* Resultado del envío, arriba del formulario (o abajo, en el del pie). */
.form-aviso { margin: 0 0 20px; padding: 12px 16px; font-size: 14px; line-height: 1.5; border: 1px solid; }
.form-aviso--ok { background: #eef9f2; color: var(--brand); border-color: var(--accent); }
.form-aviso--error { background: #fdf0f0; color: #9b1c1c; border-color: #f3c2c2; }
/* Sobre el pie oscuro: sin caja, solo el texto en su color. */
.form-aviso--oscuro { margin: 12px 0 0; padding: 0; border: 0; background: none; font-size: 13px; }
.form-aviso--oscuro.form-aviso--ok { color: var(--accent); }
.form-aviso--oscuro.form-aviso--error { color: #ffb4b4; }
