/* ============================================================
   DATATELL — Landing de Conversión
   Paleta: Charcoal #111111 | Naranja #DF6A2E | Blanco #FFFFFF
   ============================================================ */

/* ─── FUENTES AUTO-HOSPEDADAS (sin dependencia de Google Fonts) ── */

/* IBM Plex Sans — fuente variable, cubre 400–700 */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url('assets/fonts/ibm-plex-sans-400-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;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url('assets/fonts/ibm-plex-sans-400-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: 'IBM Plex Sans';
  font-style: italic;
  font-weight: 100 700;
  font-display: swap;
  src: url('assets/fonts/ibm-plex-sans-400i-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;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: italic;
  font-weight: 100 700;
  font-display: swap;
  src: url('assets/fonts/ibm-plex-sans-400i-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;
}

/* IBM Plex Mono — archivos por peso */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/ibm-plex-mono-400-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;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/ibm-plex-mono-400-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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('assets/fonts/ibm-plex-mono-500-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;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('assets/fonts/ibm-plex-mono-500-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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('assets/fonts/ibm-plex-mono-600-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;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('assets/fonts/ibm-plex-mono-600-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;
}

/* ─── VARIABLES ─────────────────────────────────────────── */
:root {
  --charcoal:       #111111;
  --charcoal-mid:   #1A1A1A;
  --charcoal-soft:  #2A2A2A;
  --orange:         #DF6A2E;
  --orange-dark:    #C4561A;
  --orange-light:   #F07A3A;
  --orange-faint:   rgba(223,106,46,.12);
  --gray-bg:        #F5F5F5;
  --gray-border:    #E5E5E5;
  --gray-mid:       #6B6B6B;
  --gray-light:     #9A9A9A;
  --white:          #FFFFFF;
  --text-dark:      #111111;
  --text-body:      #3C3C3C;
  --text-muted:     #6B6B6B;
  --text-on-dark:   rgba(255,255,255,.82);
  --font:           'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  --font-mono:      'IBM Plex Mono', 'Courier New', monospace;
  --ls-tight:       -0.02em;
  --ls-eyebrow:     0.16em;
  --radius:         10px;
  --radius-sm:      6px;
  --radius-lg:      16px;
  --shadow-sm:      0 1px 4px rgba(0,0,0,.07), 0 2px 8px rgba(0,0,0,.05);
  --shadow-md:      0 4px 16px rgba(0,0,0,.09), 0 2px 6px rgba(0,0,0,.06);
  --shadow-card:    0 2px 12px rgba(0,0,0,.08);
  --ease:           cubic-bezier(.4,0,.2,1);
  --ease-spring:    cubic-bezier(.34,1.56,.64,1);
  --transition:     200ms var(--ease);
  --container:      1180px;
  --section-py:     88px;
  --section-py-sm:  56px;

  /* Ancho de la columna de lectura de los artículos (2026-08-21).
     Va en rem y NO en ch a propósito. `ch` mide el ancho del cero, y en
     IBM Plex Sans el cero es ancho (0.6em) mientras que las minúsculas
     son bastante más angostas: el `max-width: 68ch` que había daba 680px,
     que en texto real son 95 caracteres por línea — muy por encima de los
     65-75 que se leen cómodos. Medido en el navegador, no calculado a ojo.
     En rem además todos los bloques comparten el MISMO ancho aunque
     tengan tamaños de letra distintos, que es lo que hace que el titular,
     la firma, la figura y el cuerpo caigan sobre el mismo eje.
     33rem = 528px ≈ 74 caracteres por línea. */
  --post-measure:   33rem;
}

/* ─── RESET ─────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }
html { scroll-behavior: smooth; font-size: 16px; -webkit-tap-highlight-color: transparent; }
body {
  font-family: var(--font);
  color: var(--text-body);
  background: var(--white);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}
img  { display: block; max-width: 100%; height: auto; }
a    { text-decoration: none; color: inherit; }
ul, ol { list-style: none; }
button { cursor: pointer; border: none; background: none; font-family: inherit; }
textarea, input, select { font-family: inherit; }

/* ─── NOSCRIPT / reduced-motion fallback ────────────────── */
.reveal { opacity: 1; transform: none; }

/* ─── TIPOGRAFÍA ────────────────────────────────────────── */
h1, h2, h3, h4 { line-height: 1.18; font-weight: 700; color: var(--text-dark); }
h1 { font-size: clamp(2rem, 5vw, 3.4rem); letter-spacing: var(--ls-tight); }
h2 { font-size: clamp(1.55rem, 3vw, 2.25rem); letter-spacing: var(--ls-tight); }
h3 { font-size: 1.05rem; font-weight: 600; }
p  { color: var(--text-body); }

/* ─── LAYOUT ────────────────────────────────────────────── */
.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 24px;
}
@media (min-width: 768px)  { .container { padding: 0 40px; } }
@media (min-width: 1280px) { .container { padding: 0 24px; } }

.section-header {
  max-width: 680px;
  margin-bottom: 52px;
}
.section-header h2 { margin-bottom: 14px; }
.section-header p  { color: var(--text-muted); font-size: 1.05rem; }

/* ─── EYEBROW ────────────────────────────────────────────── */
.eyebrow {
  display: inline-block;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--orange);
  margin-bottom: 18px;
  font-family: var(--font-mono);
}
.eyebrow--dark { color: var(--orange); }

/* ─── BUTTONS ───────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 13px 28px;
  font-size: .95rem;
  font-weight: 600;
  border-radius: var(--radius);
  transition: background var(--transition), color var(--transition),
              border-color var(--transition), transform var(--transition),
              box-shadow var(--transition);
  white-space: nowrap;
  line-height: 1;
}
.btn:active { transform: scale(.98); }

.btn--primary {
  background: var(--orange);
  color: var(--white);
  border: 2px solid var(--orange);
}
.btn--primary:hover {
  background: var(--orange-dark);
  border-color: var(--orange-dark);
  box-shadow: 0 4px 16px rgba(223,106,46,.35);
}

.btn--outline {
  background: transparent;
  color: var(--white);
  border: 2px solid rgba(255,255,255,.45);
}
.btn--outline:hover {
  border-color: var(--white);
  background: rgba(255,255,255,.08);
}

.btn--white {
  background: var(--white);
  color: var(--orange);
  border: 2px solid var(--white);
  font-weight: 700;
}
.btn--white:hover {
  background: rgba(255,255,255,.9);
  box-shadow: 0 4px 16px rgba(0,0,0,.15);
}

.btn--nav {
  padding: 9px 20px;
  font-size: .87rem;
  background: transparent;
  color: var(--white);
  border: 1.5px solid rgba(255,255,255,.4);
  border-radius: var(--radius-sm);
}
.btn--nav:hover {
  background: var(--orange);
  border-color: var(--orange);
}

.btn--soporte {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 110px;
  height: 42px;
  padding: 0 16px;
  background: var(--orange);
  color: var(--white);
  border: 2px solid var(--orange);
  border-radius: var(--radius-sm);
  font-size: .87rem;
  font-weight: 700;
  white-space: nowrap;
}
.btn--soporte:hover {
  background: var(--orange-dark);
  border-color: var(--orange-dark);
  box-shadow: 0 4px 16px rgba(223,106,46,.35);
}
.btn--soporte--footer {
  margin-top: 14px;
  width: auto;
  height: auto;
  padding: 10px 20px;
}

.btn--full { width: 100%; }

/* ─── SECTION LABEL (video section) ─────────────────────── */
.section-label {
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--white);
  text-align: center;
  margin-bottom: 32px;
}

/* ─── HIGHLIGHT QUOTE ───────────────────────────────────── */
.highlight-quote {
  display: block;
  margin-top: 28px;
  padding: 18px 24px;
  border-left: 3px solid var(--orange);
  background: rgba(223,106,46,.06);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text-dark);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-style: normal;
  line-height: 1.5;
}

/* ════════════════════════════════════════════════════════════
   NAVEGACIÓN
   ════════════════════════════════════════════════════════════ */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  transition: background var(--transition), box-shadow var(--transition);
}
.nav.scrolled {
  background: rgba(17,17,17,.97);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 1px 0 rgba(255,255,255,.07);
}
.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 72px;
}
.nav__logo img { height: 42px; width: auto; }

.nav__menu {
  display: none;
  align-items: center;
  gap: 32px;
}
.nav__link {
  font-size: .9rem;
  font-weight: 600;
  color: rgba(255,255,255,.75);
  transition: color var(--transition);
}
.nav__link:hover { color: var(--white); }

/* Hamburger */
.nav__toggle {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width: 26px; height: 18px;
  padding: 0;
  z-index: 110;
}
.nav__toggle span {
  display: block;
  height: 2px;
  background: var(--white);
  border-radius: 2px;
  transition: transform .28s var(--ease), opacity .2s;
}
.nav__toggle.active span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
.nav__toggle.active span:nth-child(2) { opacity: 0; }
.nav__toggle.active span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

/* Mobile menu open */
.nav__menu.open {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  position: fixed;
  top: 72px; left: 0; right: 0;
  background: var(--charcoal-mid);
  padding: 24px;
  border-top: 1px solid rgba(255,255,255,.07);
}
.nav__menu.open .nav__link { font-size: 1rem; color: var(--white); padding: 8px 0; }
.nav__menu.open .btn--nav {
  width: 100%;
  margin-top: 8px;
  text-align: center;
  justify-content: center;
  background: var(--orange);
  border-color: var(--orange);
}
.nav__menu.open .btn--soporte {
  width: 100%;
  height: auto;
  padding: 12px 0;
  margin-top: 8px;
  text-align: center;
}

@media (min-width: 860px) {
  .nav__menu { display: flex !important; }
  .nav__toggle { display: none; }
}

/* ════════════════════════════════════════════════════════════
   HERO
   ════════════════════════════════════════════════════════════ */
.hero {
  background: var(--charcoal);
  min-height: 100vh;
  display: flex;
  align-items: center;
  padding: 120px 0 80px;
  overflow: hidden;
  position: relative;
}
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 60% 60% at 70% 50%, rgba(223,106,46,.07) 0%, transparent 70%);
  pointer-events: none;
}

.hero__layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 48px;
  align-items: center;
}
.hero__content { max-width: 620px; }

.hero__title {
  color: var(--white);
  margin-bottom: 20px;
  line-height: 1.14;
}
.hero__title::after {
  content: '';
  display: block;
  width: 52px; height: 3px;
  background: var(--orange);
  border-radius: 2px;
  margin-top: 20px;
}

.hero__sub {
  color: var(--text-on-dark);
  font-size: 1.05rem;
  margin-bottom: 36px;
  max-width: 520px;
}

.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 20px;
}

.hero__note {
  font-size: .82rem;
  color: rgba(255,255,255,.45);
  letter-spacing: .02em;
}

/* Decoración geométrica derecha */
.hero__deco {
  display: none;
  position: relative;
  width: 360px; height: 360px;
  flex-shrink: 0;
}
.deco__grid {
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(circle, rgba(223,106,46,.22) 1px, transparent 1px);
  background-size: 28px 28px;
  border-radius: var(--radius-lg);
}
.deco__ring {
  position: absolute;
  border-radius: 50%;
  border: 1.5px solid rgba(223,106,46,.2);
}
.deco__ring--1 {
  width: 240px; height: 240px;
  top: 50%; left: 50%;
  transform: translate(-50%,-50%);
}
.deco__ring--2 {
  width: 160px; height: 160px;
  top: 50%; left: 50%;
  transform: translate(-50%,-50%);
  border-color: rgba(223,106,46,.35);
}
.deco__line {
  position: absolute;
  width: 2px; height: 80%;
  background: linear-gradient(to bottom, transparent, rgba(223,106,46,.4), transparent);
  top: 10%; left: 50%;
  transform: translateX(-50%);
}

@media (min-width: 900px) {
  .hero__layout { grid-template-columns: 1fr 360px; }
  .hero__deco { display: block; }
}

/* ════════════════════════════════════════════════════════════
   VIDEO PLACEHOLDER
   ════════════════════════════════════════════════════════════ */
.video-section {
  background: var(--charcoal-mid);
  padding: var(--section-py) 0;
}

.video-wrap {
  max-width: 820px;
  margin: 0 auto 24px;
  /* Proporción 16:9 */
  position: relative;
  width: 100%;
  padding-top: 56.25%;
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.video-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  background: var(--charcoal-soft);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: var(--radius-lg);
}

.play-btn {
  width: 72px; height: 72px;
  border-radius: 50%;
  background: var(--orange);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--white);
  opacity: .85;
}

.video-placeholder__label {
  font-size: .9rem;
  color: rgba(255,255,255,.4);
  letter-spacing: .03em;
}

.video-caption {
  max-width: 820px;
  margin: 0 auto;
  text-align: center;
  font-size: .9rem;
  color: rgba(255,255,255,.38);
}

/* ════════════════════════════════════════════════════════════
   DOLORES / PAIN SECTION
   ════════════════════════════════════════════════════════════ */
.pain-section {
  background: var(--white);
  padding: var(--section-py) 0;
}

.cards-grid {
  display: grid;
  gap: 20px;
  grid-template-columns: 1fr;
}
@media (min-width: 640px)  { .cards-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) {
  .cards-grid--pain      { grid-template-columns: repeat(3, 1fr); }
  .cards-grid--solutions { grid-template-columns: repeat(3, 1fr); }
}

.pain-card {
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-radius: var(--radius);
  padding: 28px;
  transition: box-shadow var(--transition), transform var(--transition);
}
.pain-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.pain-card__icon {
  width: 48px; height: 48px;
  border-radius: var(--radius-sm);
  background: var(--orange-faint);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--orange);
  margin-bottom: 16px;
}

.pain-card h3 {
  font-size: 1rem;
  margin-bottom: 8px;
  color: var(--text-dark);
}
.pain-card p {
  font-size: .9rem;
  color: var(--text-muted);
  line-height: 1.6;
}

/* ════════════════════════════════════════════════════════════
   EMPATÍA INSTITUCIONAL
   ════════════════════════════════════════════════════════════ */
.empathy-section {
  background: var(--gray-bg);
  padding: var(--section-py) 0;
}

.empathy-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 48px;
  align-items: center;
}
@media (min-width: 860px) {
  .empathy-layout { grid-template-columns: 1fr 320px; }
}

.empathy-text h2   { margin-bottom: 20px; }
.empathy-text p    { color: var(--text-muted); margin-bottom: 14px; font-size: 1.02rem; }
.empathy-text p strong { color: var(--text-dark); }

/* Visual decorativo derecho */
.empathy-visual {
  display: none;
}
.empathy-accent {
  position: relative;
  width: 220px; height: 220px;
  margin: 0 auto;
}
.accent-ring {
  position: absolute;
  border-radius: 50%;
  border: 2px solid;
  top: 50%; left: 50%;
  transform: translate(-50%,-50%);
}
.accent-ring--lg {
  width: 200px; height: 200px;
  border-color: rgba(223,106,46,.2);
}
.accent-ring--sm {
  width: 120px; height: 120px;
  border-color: rgba(223,106,46,.4);
}
.accent-dot {
  position: absolute;
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--orange);
  top: 50%; left: 50%;
  transform: translate(-50%,-50%);
  opacity: .9;
}

@media (min-width: 860px) {
  .empathy-visual { display: flex; align-items: center; justify-content: center; }
}

/* ════════════════════════════════════════════════════════════
   SOLUCIONES
   ════════════════════════════════════════════════════════════ */
.solutions-section {
  background: var(--white);
  padding: var(--section-py) 0;
}

.solution-card {
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-radius: var(--radius);
  padding: 28px;
  transition: box-shadow var(--transition), transform var(--transition);
  position: relative;
  overflow: hidden;
}
.solution-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--orange);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--transition);
}
.solution-card:hover::before { transform: scaleX(1); }
.solution-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.solution-card__icon {
  width: 48px; height: 48px;
  border-radius: var(--radius-sm);
  background: var(--orange-faint);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--orange);
  margin-bottom: 16px;
}
.solution-card h3 { font-size: 1rem; margin-bottom: 8px; }
.solution-card p  { font-size: .9rem; color: var(--text-muted); line-height: 1.6; }

/* ════════════════════════════════════════════════════════════
   MARCAS / LOGOS
   ════════════════════════════════════════════════════════════ */
.brands-section {
  background: var(--gray-bg);
  padding: var(--section-py) 0;
}

.brands-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  align-items: center;
}
@media (min-width: 540px)  { .brands-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 860px)  { .brands-grid { grid-template-columns: repeat(4, 1fr); gap: 20px; } }
/* auto-fit en vez de un número fijo: la fila se ajusta sola a la cantidad
   de marcas que haya, sin dejar huecos si se agrega o se quita alguna. */
@media (min-width: 1100px) { .brands-grid { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); } }

/* ── Tira de marcas bajo el hero de las páginas de solución ──
   Añadida el 2026-08-25 para la página de inventario de red. Reutiliza
   .brands-grid y .brand-item del muro de index.html; solo baja la altura
   y quita el peso visual, porque acá es un apoyo del hero, no la sección
   protagonista. Si se usa en otra página de solución, basta con repetir
   el marcado: no hay nada específico de inventario en estas reglas. */
.brands-strip {
  padding-top: 28px;
  padding-bottom: 28px;
}
.brands-strip__eyebrow {
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gray-text, #6b7280);
  margin: 0 0 14px;
  text-align: center;
}
.brands-grid--strip .brand-item {
  min-height: 72px;
  padding: 12px 14px;
}
.brands-grid--strip .brand-item img { max-height: 38px; }

.brand-item {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px 16px;
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-radius: var(--radius);
  transition: box-shadow var(--transition), transform var(--transition);
  min-height: 100px;
}
.brand-item:hover {
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}

.brand-item img {
  max-height: 52px;
  width: auto;
  /* 2026-08-28 · Mismo arreglo que en `.client-cell img`: el tope era
     `150px` fijo y en celular la celda queda con unos 137px útiles, así
     que los logos anchos —Extreme— se salían por la derecha. */
  max-width: min(150px, 100%);
  object-fit: contain;
  /* Homogeneización visual: todos en escala de grises */
  filter: grayscale(100%) brightness(0.55) contrast(1.1);
  opacity: .8;
  transition: filter 250ms var(--ease), opacity 250ms var(--ease);
}
.brand-item:hover img {
  filter: grayscale(0%) brightness(1) contrast(1);
  opacity: 1;
}

/* ── Compensaciones ópticas por marca (auditoría 2026-08-07) ──
   Igualan el peso visual medido en pantalla (porcentaje de "tinta")
   ajustando solo la presentación — encuadre, escala y filtro — sin
   editar los archivos de marca. Referencia: Extreme ~31 % de tinta.
   Medido antes del ajuste: Microchip 13 % (PNG 3840×2160 con márgenes
   horneados), Netcom 10,6 % (isotipo cuadrado en fila horizontal),
   Airspan limitado por su proporción 300×44. */
.brand-item[data-brand="microchip"] {
  /* el recorte por escala no debe desbordar la tarjeta */
  overflow: hidden;
}
.brand-item[data-brand="microchip"] img {
  /* compensa el aire horneado del PNG: recorte óptico, no edición */
  transform: scale(1.4);
}
.brand-item[data-brand="netcom"] img {
  /* isotipo cuadrado: toma más alto de fila y un filtro menos lavado.
     Solución de fondo pendiente: lockup horizontal oficial del partner. */
  max-height: 48px;
  filter: grayscale(100%) brightness(0.4) contrast(1.15);
  opacity: .9;
}
.brand-item[data-brand="netcom"]:hover img {
  filter: grayscale(0%) brightness(1) contrast(1);
  opacity: 1;
}
.brand-item[data-brand="airspan"] img {
  /* wordmark muy horizontal (300×44): el ancho de la celda lo limita
     antes que max-width, así que se escala visualmente igual que
     Microchip para acercarlo al peso de sus vecinos */
  transform: scale(1.2);
}

/* ── Marca sin archivo de logo: se compone como wordmark ──
   Mismo alto, borde y peso visual que las tarjetas con imagen, para que
   no se lea como un hueco ni como una imagen que no cargó. El color sale
   de medir el gris promedio de los logos ya filtrados (31/255), así la
   tarjeta pesa lo mismo que sus vecinas. */
.brand-wordmark {
  font-family: var(--font);
  font-weight: 700;
  font-size: .95rem;
  letter-spacing: -.02em;
  line-height: 1;
  white-space: nowrap;
  color: #1F1F1F;
  opacity: .8;
  transition: opacity 250ms var(--ease);
}

/* Nombre compuesto largo (VertiGIS ConnectMaster): baja un punto y permite
   dos líneas para que no desborde la celda. */
.brand-wordmark--long {
  font-size: .82rem;
  white-space: normal;
  text-align: center;
  line-height: 1.25;
}

/* Variante estática: sin modal asociado todavía, así que no se comporta
   como botón ni ofrece el hint "Ver tecnología" — no promete una
   interacción que no existe. (Sin uso desde 2026-08-10 — la celda de
   VertiGIS ConnectMaster ya abre modal — pero se conserva por si vuelve
   a entrar una marca sin ficha.) */
.brand-item--static {
  cursor: default;
}
.brand-item--static:hover {
  box-shadow: none;
  transform: none;
}

/* Con una cantidad impar de marcas, la última quedaba sola a la izquierda
   con el espacio de al lado vacío. Se centra cuando eso pasa. */
@media (max-width: 539px) {
  .brands-grid > *:last-child:nth-child(odd) {
    grid-column: 1 / -1;
    justify-self: center;
    width: calc(50% - 8px);
  }
}
@media (min-width: 540px) and (max-width: 859px) {
  .brands-grid > *:last-child:nth-child(3n + 1) {
    grid-column: 1 / -1;
    justify-self: center;
    width: calc(33.333% - 11px);
  }
}

/* ════════════════════════════════════════════════════════════
   CREDIBILIDAD / CIFRAS
   ════════════════════════════════════════════════════════════ */
.credibility-section {
  background: var(--charcoal);
  padding: var(--section-py) 0;
}

.credibility-title {
  color: var(--white);
  text-align: center;
  margin-bottom: 56px;
}
.credibility-title::after {
  content: '';
  display: block;
  width: 40px; height: 3px;
  background: var(--orange);
  border-radius: 2px;
  margin: 16px auto 0;
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 2px;
}
@media (min-width: 860px) {
  .stats-grid { grid-template-columns: repeat(4, 1fr); }
}

.stat-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 36px 24px;
  border: 1px solid rgba(255,255,255,.06);
}
.stat-item:first-child { border-radius: var(--radius) 0 0 var(--radius); }
.stat-item:last-child  { border-radius: 0 var(--radius) var(--radius) 0; }
@media (max-width: 859px) {
  .stat-item:first-child  { border-radius: var(--radius) 0 0 0; }
  .stat-item:nth-child(2) { border-radius: 0 var(--radius) 0 0; }
  .stat-item:nth-child(3) { border-radius: 0 0 0 var(--radius); }
  .stat-item:last-child   { border-radius: 0 0 var(--radius) 0; }
}

.stat-number-wrap {
  display: flex;
  align-items: flex-start;
  gap: 2px;
  margin-bottom: 12px;
}
.stat-number {
  font-size: clamp(2.4rem, 5vw, 3.4rem);
  font-weight: 700;
  color: var(--orange);
  line-height: 1;
}
.stat-suffix {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--orange);
  margin-top: 4px;
}
.stat-item > p {
  font-size: .86rem;
  color: rgba(255,255,255,.5);
  line-height: 1.5;
  max-width: 160px;
}

/* ════════════════════════════════════════════════════════════
   RESPONSABILIDAD SOCIAL
   ════════════════════════════════════════════════════════════ */
.responsibility-section {
  background: var(--white);
  padding: var(--section-py) 0;
}
.responsibility-layout { max-width: 720px; }
.responsibility-text h2 { margin-bottom: 20px; }
.responsibility-text p  { color: var(--text-muted); margin-bottom: 14px; font-size: 1.02rem; }

/* ════════════════════════════════════════════════════════════
   CTA INTERMEDIO (naranja)
   ════════════════════════════════════════════════════════════ */
.cta-mid {
  background: var(--orange);
  padding: 72px 0;
}
.cta-mid__inner {
  max-width: 680px;
  margin: 0 auto;
  text-align: center;
}
.cta-mid__inner h2 {
  color: var(--white);
  margin-bottom: 14px;
}
.cta-mid__inner p {
  color: rgba(255,255,255,.82);
  font-size: 1.05rem;
  margin-bottom: 32px;
}
.cta-mid__note {
  display: block;
  margin-top: 16px;
  font-size: .82rem;
  color: rgba(255,255,255,.55);
}

/* ════════════════════════════════════════════════════════════
   FORMULARIO DE CONTACTO
   ════════════════════════════════════════════════════════════ */
.form-section {
  background: var(--gray-bg);
  padding: var(--section-py) 0;
}

.form-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 48px;
  align-items: start;
}
@media (min-width: 900px) {
  .form-layout { grid-template-columns: 1fr 1fr; }
}

/* Columna izquierda */
.form-intro h2 { margin-bottom: 16px; }
.form-intro > p { color: var(--text-muted); margin-bottom: 28px; font-size: 1.02rem; }

.contact-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 28px;
}
.contact-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: .95rem;
  color: var(--text-muted);
}
.contact-list__icon { color: var(--orange); flex-shrink: 0; }

.whatsapp-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 22px;
  background: #25D366;
  color: var(--white);
  font-weight: 600;
  font-size: .9rem;
  border-radius: var(--radius);
  transition: background var(--transition), transform var(--transition);
}
.whatsapp-link:hover {
  background: #1fbc5a;
  transform: translateY(-1px);
}

/* Formulario */
.contact-form {
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-radius: var(--radius-lg);
  padding: 36px 32px;
  box-shadow: var(--shadow-sm);
  position: relative;
}

.form-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}
@media (min-width: 540px) { .form-row { grid-template-columns: 1fr 1fr; } }

.form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 16px;
}
.form-group:last-of-type { margin-bottom: 0; }

/* Campo auxiliar: no participa del flujo visual ni del orden de lectura */
.form-group--aux {
  position: absolute !important;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
  margin: 0;
}

.form-group label {
  font-size: .84rem;
  font-weight: 600;
  color: var(--text-dark);
}
.req  { color: var(--orange); }
.opt  { color: var(--gray-light); font-weight: 400; }

.form-group input,
.form-group select,
.form-group textarea {
  padding: 11px 14px;
  border: 1.5px solid var(--gray-border);
  border-radius: var(--radius-sm);
  font-size: .95rem;
  color: var(--text-dark);
  background: var(--white);
  transition: border-color var(--transition), box-shadow var(--transition);
  outline: none;
  -webkit-appearance: none;
}
.form-group select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%23767676' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 38px;
}
.form-group select:invalid { color: var(--gray-light); }
.form-group input::placeholder,
.form-group textarea::placeholder { color: var(--gray-light); }
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  border-color: var(--orange);
  box-shadow: 0 0 0 3px rgba(223,106,46,.12);
}
.form-group input.is-error,
.form-group select.is-error,
.form-group textarea.is-error { border-color: #e63946; }

.form-group textarea { resize: vertical; min-height: 100px; }

.form-group--textarea { position: relative; }
.char-count {
  position: absolute;
  bottom: 8px; right: 12px;
  font-size: .75rem;
  color: var(--gray-light);
  pointer-events: none;
}

.form-check {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 10px;
  margin: 16px 0;
}
/* El mensaje de error ocupa su propia línea debajo de la casilla; si no,
   el flex lo mete como tercera columna y lo aplasta contra el borde. */
.form-check .form-error { flex-basis: 100%; }
.form-check input[type="checkbox"] {
  /* 24×24: mínimo de objetivo táctil WCAG 2.2 (2.5.8) — es un control
     obligatorio para enviar el formulario */
  width: 24px; height: 24px;
  border: 1.5px solid var(--gray-border);
  border-radius: 4px;
  cursor: pointer;
  accent-color: var(--orange);
  flex-shrink: 0;
}
.form-check label {
  font-size: .88rem;
  color: var(--text-muted);
  cursor: pointer;
}
.text-link {
  color: var(--orange);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.form-error {
  font-size: .78rem;
  color: #e63946;
  min-height: 16px;
}

.form-actions { margin-top: 4px; }

/* Submit button loading state */
.btn__loading {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.spinner {
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.form-note {
  margin-top: 16px;
  font-size: .78rem;
  color: var(--gray-light);
  line-height: 1.5;
}

/* Éxito */
.form-success {
  position: absolute;
  inset: 0;
  background: var(--white);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 12px;
  padding: 40px;
}
.form-success[hidden] { display: none; }
.form-success__icon {
  width: 64px; height: 64px;
  border-radius: 50%;
  background: rgba(223,106,46,.1);
  color: var(--orange);
  display: flex;
  align-items: center;
  justify-content: center;
}
.form-success h3 { font-size: 1.25rem; }
.form-success p  { color: var(--text-muted); }

/* Aviso resultado WhatsApp */
.wa-notice {
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  font-size: .875rem;
  line-height: 1.55;
  margin-top: 12px;
}
.wa-notice[hidden] { display: none; }
.wa-notice--success {
  background: #f0fdf4;
  border: 1px solid #86efac;
  border-left: 3px solid #22c55e;
  color: #15803d;
}
.wa-notice--error {
  background: #fff5f5;
  border: 1px solid #fcc;
  border-left: 3px solid #e63946;
  color: #c1121f;
}
.wa-notice--info {
  background: #f0f7ff;
  border: 1px solid #bfdbfe;
  border-left: 3px solid #3b82f6;
  color: #1e40af;
}
.wa-notice a { color: inherit; font-weight: 600; text-decoration: underline; }

/* Error de envío (backend/red) */
.form-send-error {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 14px 16px;
  background: #fff5f5;
  border: 1px solid #fcc;
  border-left: 3px solid #e63946;
  border-radius: var(--radius-sm);
  margin-top: 12px;
  color: #c1121f;
  font-size: .875rem;
  line-height: 1.55;
}
.form-send-error[hidden] { display: none; }
.form-send-error svg {
  flex-shrink: 0;
  margin-top: 2px;
  color: #e63946;
}
.form-send-error a {
  color: #c1121f;
  font-weight: 600;
  text-decoration: underline;
}

/* ════════════════════════════════════════════════════════════
   FOOTER
   ════════════════════════════════════════════════════════════ */
.footer {
  background: var(--charcoal);
  padding: 64px 0 0;
}

.footer__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 40px;
  padding-bottom: 48px;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
@media (min-width: 640px)  { .footer__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .footer__grid { grid-template-columns: 2fr 1fr 1.2fr 1fr; gap: 32px; } }

.footer__brand img    { margin-bottom: 14px; }
.footer__brand p      { font-size: .88rem; color: rgba(255,255,255,.45); line-height: 1.6; }
.footer__cj           { font-size: .78rem; color: rgba(255,255,255,.25); margin-top: 8px; }

.footer__nav h4,
.footer__contact h4,
.footer__social h4 {
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(255,255,255,.35);
  margin-bottom: 16px;
}

.footer__nav ul { display: flex; flex-direction: column; gap: 10px; }
.footer__nav a  {
  font-size: .9rem;
  color: rgba(255,255,255,.55);
  transition: color var(--transition);
}
.footer__nav a:hover { color: var(--white); }

.footer__contact ul { display: flex; flex-direction: column; gap: 10px; }
.footer__contact li { font-size: .9rem; color: rgba(255,255,255,.45); }

.social-links {
  display: flex;
  gap: 12px;
}
.social-links a {
  width: 38px; height: 38px;
  border-radius: var(--radius-sm);
  background: rgba(255,255,255,.07);
  display: flex; align-items: center; justify-content: center;
  color: rgba(255,255,255,.6);
  transition: background var(--transition), color var(--transition);
}
.social-links a:hover {
  background: var(--orange);
  color: var(--white);
}

.footer__bottom {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 24px 0;
  align-items: flex-start;
}
@media (min-width: 640px) {
  .footer__bottom {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
  }
}
.footer__bottom p { font-size: .84rem; color: rgba(255,255,255,.3); }

.footer__legal-links { display: flex; gap: 24px; }
.footer__legal-links a {
  font-size: .84rem;
  color: rgba(255,255,255,.3);
  transition: color var(--transition);
}
.footer__legal-links a:hover { color: rgba(255,255,255,.7); }

/* ════════════════════════════════════════════════════════════
   ANIMACIONES DE SCROLL (reveal)
   ════════════════════════════════════════════════════════════
   El tipo `screen` es obligatorio: sin él la media query equivale a
   `all` y el opacity:0 aplica también al imprimir — todo bloque no
   scrolleado salía en blanco en el PDF (auditoría 2026-08-07).
   Refuerzo adicional en script.js: listener de `beforeprint`. */
@media screen and (prefers-reduced-motion: no-preference) {
  .reveal {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity .5s var(--ease), transform .5s var(--ease);
  }
  .reveal.visible {
    opacity: 1;
    transform: translateY(0);
  }
  /* Stagger para cards (asignado desde JS) */
  .reveal[data-delay="1"] { transition-delay: .08s; }
  .reveal[data-delay="2"] { transition-delay: .16s; }
  .reveal[data-delay="3"] { transition-delay: .24s; }
  .reveal[data-delay="4"] { transition-delay: .32s; }
  .reveal[data-delay="5"] { transition-delay: .40s; }
  .reveal[data-delay="6"] { transition-delay: .48s; }
}

/* ════════════════════════════════════════════════════════════
   RESPONSIVE AJUSTES FINALES
   ════════════════════════════════════════════════════════════ */
@media (max-width: 640px) {
  :root {
    --section-py: var(--section-py-sm);
  }
  .hero__ctas { flex-direction: column; }
  .hero__ctas .btn { width: 100%; justify-content: center; }
  .contact-form { padding: 24px 20px; }
  .stat-item { padding: 28px 16px; }
  .cta-mid { padding: 56px 0; }
  .section-header { margin-bottom: 36px; }
}

/* Accesibilidad: foco visible */
:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
  border-radius: 3px;
}

/* ════════════════════════════════════════════════════════════
   CONTEXTUAL CTA — al final de secciones clave
   ════════════════════════════════════════════════════════════ */
.ctx-cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 44px;
  padding: 20px 28px;
  background: var(--gray-bg);
  border: 1px solid var(--gray-border);
  border-radius: var(--radius);
  transition: border-color var(--transition);
}
.ctx-cta:hover { border-color: rgba(223,106,46,.25); }

/* Variante para secciones con fondo gris (marcas) */
.ctx-cta--white { background: var(--white); }

.ctx-cta p {
  font-size: .97rem;
  font-weight: 500;
  color: var(--text-dark);
  margin: 0;
}

.ctx-cta__link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: .9rem;
  font-weight: 600;
  color: var(--orange);
  white-space: nowrap;
  transition: color var(--transition), gap var(--transition);
}
.ctx-cta__link svg {
  flex-shrink: 0;
  transition: transform var(--transition);
}
.ctx-cta__link:hover { color: var(--orange-dark); }
.ctx-cta__link:hover svg { transform: translateX(4px); }

@media (max-width: 600px) {
  .ctx-cta { flex-direction: column; align-items: flex-start; padding: 18px 20px; }
}

/* ════════════════════════════════════════════════════════════
   STICKY CTA — aparece al hacer scroll, discreto y funcional
   ════════════════════════════════════════════════════════════ */
.sticky-cta {
  position: fixed;
  bottom: 28px;
  right: 24px;
  z-index: 89;
  display: flex;
  align-items: center;
  gap: 8px;
  /* Empieza abajo y oculto */
  transform: translateY(20px);
  opacity: 0;
  pointer-events: none;
  transition: transform .4s var(--ease-spring), opacity .3s var(--ease);
}
.sticky-cta.visible {
  transform: translateY(0);
  opacity: 1;
  pointer-events: auto;
}

.sticky-cta__main {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 13px 22px;
  background: var(--charcoal);
  color: var(--white);
  font-size: .87rem;
  font-weight: 600;
  border-radius: 100px;
  box-shadow: 0 4px 20px rgba(0,0,0,.3), 0 1px 4px rgba(0,0,0,.2);
  white-space: nowrap;
  transition: background var(--transition), transform var(--transition), box-shadow var(--transition);
  letter-spacing: .01em;
}
.sticky-cta__main svg { transition: transform var(--transition); flex-shrink: 0; }
.sticky-cta__main:hover {
  background: var(--charcoal-soft);
  transform: translateY(-2px);
  box-shadow: 0 8px 28px rgba(0,0,0,.32);
}
.sticky-cta__main:hover svg { transform: translateX(4px); }

.sticky-cta__wa {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 13px 16px;
  background: #25D366;
  color: var(--white);
  font-size: .87rem;
  font-weight: 600;
  border-radius: 100px;
  box-shadow: 0 4px 20px rgba(0,0,0,.18);
  white-space: nowrap;
  transition: background var(--transition), transform var(--transition), box-shadow var(--transition);
}
.sticky-cta__wa:hover {
  background: #1fbc5a;
  transform: translateY(-2px);
  box-shadow: 0 6px 24px rgba(37,211,102,.35);
}

/* Mobile: barra full-width anclada al bottom */
@media (max-width: 640px) {
  .sticky-cta {
    bottom: 0; right: 0; left: 0;
    gap: 10px;
    padding: 12px 16px;
    background: rgba(17,17,17,.97);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-top: 1px solid rgba(255,255,255,.08);
    border-radius: 0;
    box-shadow: 0 -4px 24px rgba(0,0,0,.22);
    /* anular la transform individual — la barra sube desde abajo */
    transform: translateY(100%);
  }
  .sticky-cta.visible { transform: translateY(0); }

  .sticky-cta__main {
    flex: 1;
    justify-content: center;
    background: var(--orange);
    border-radius: var(--radius);
    box-shadow: none;
    font-size: .85rem;
  }
  .sticky-cta__main:hover {
    background: var(--orange-dark);
    transform: none;
    box-shadow: none;
  }
  .sticky-cta__wa {
    border-radius: var(--radius);
    box-shadow: none;
    padding: 13px 16px;
  }
  .sticky-cta__wa span { display: none; }
  .sticky-cta__wa { padding: 13px 18px; }
}

/* ════════════════════════════════════════════════════════════
   MEJORAS DE BOTONES — hover premium, escala, sombra
   ════════════════════════════════════════════════════════════ */

/* Primary más visible y con elevación en hover */
.btn--primary {
  font-size: 1rem;
  padding: 14px 30px;
  letter-spacing: .01em;
}
.btn--primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 24px rgba(223,106,46,.4);
}
.btn--primary:active { transform: scale(.97) translateY(0); }

/* Outline más visible sobre oscuro */
.btn--outline {
  border-color: rgba(255,255,255,.6);
  letter-spacing: .01em;
}
.btn--outline:hover {
  border-color: var(--white);
  background: rgba(255,255,255,.1);
  transform: translateY(-1px);
}

/* White button (CTA naranja) */
.btn--white:hover { transform: translateY(-2px); }

/* ════════════════════════════════════════════════════════════
   MEJORAS DE CARDS — hover más elegante y con transición GPU
   ════════════════════════════════════════════════════════════ */
.pain-card, .solution-card {
  will-change: transform, box-shadow;
}

/* Pain card: hover con borde y escala de ícono */
.pain-card:hover {
  border-color: rgba(223,106,46,.2);
  transform: translateY(-3px);
  box-shadow: 0 8px 28px rgba(0,0,0,.1), 0 2px 8px rgba(0,0,0,.06);
}
.pain-card__icon {
  transition: background var(--transition), transform .25s var(--ease-spring);
}
.pain-card:hover .pain-card__icon {
  background: rgba(223,106,46,.18);
  transform: scale(1.08);
}

/* Solution card: ícono escala */
.solution-card__icon {
  transition: background var(--transition), transform .25s var(--ease-spring);
}
.solution-card:hover .solution-card__icon {
  background: rgba(223,106,46,.18);
  transform: scale(1.08);
}
.solution-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 8px 28px rgba(0,0,0,.1), 0 2px 8px rgba(0,0,0,.06);
}

/* Brand items: transición suave */
.brand-item { will-change: transform, box-shadow; }


/* ═══════════════════════════════════════════════════════════
   EXPERIENCIA EN ACCIÓN
   ═══════════════════════════════════════════════════════════ */
.experience-section {
  background: var(--charcoal-mid);
  padding: var(--section-py) 0;
}
.section-header--light h2 {
  color: var(--white);
}
.section-header--light p {
  color: rgba(255,255,255,.6);
}

.exp-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin-top: 40px;
}

.exp-card {
  background: var(--charcoal-soft);
  border: 1px solid rgba(255,255,255,.07);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
  will-change: transform;
}
.exp-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 36px rgba(0,0,0,.4);
  border-color: rgba(223,106,46,.25);
}

.exp-card__thumb {
  position: relative;
  width: 100%;
  padding-top: 56.25%; /* 16:9 */
  background: var(--charcoal);
}

.exp-card__play {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 54px; height: 54px;
  border-radius: 50%;
  background: rgba(223,106,46,.75);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--white);
  transition: background var(--transition), transform .22s var(--ease-spring);
}
.exp-card:hover .exp-card__play {
  background: var(--orange);
  transform: translate(-50%, -50%) scale(1.08);
}

.exp-card__badge {
  position: absolute;
  bottom: 10px; left: 12px;
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: rgba(255,255,255,.5);
  background: rgba(0,0,0,.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  padding: 4px 9px;
  border-radius: 4px;
}

.exp-card__body {
  padding: 20px 22px 24px;
}
.exp-card__body h3 {
  color: var(--white);
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 8px;
  line-height: 1.4;
}
.exp-card__body p {
  font-size: .875rem;
  color: rgba(255,255,255,.52);
  line-height: 1.6;
}

@media (max-width: 768px) {
  .exp-grid {
    grid-template-columns: 1fr;
    max-width: 480px;
    margin-left: auto;
    margin-right: auto;
  }
}


/* ═══════════════════════════════════════════════════════════
   RECURSOS TÉCNICOS / BLOG
   ═══════════════════════════════════════════════════════════ */
.blog-section {
  background: var(--gray-bg);
  padding: var(--section-py) 0;
}

.blog-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
  margin-top: 40px;
}

.blog-card {
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-radius: var(--radius);
  padding: 24px 26px 22px;
  display: flex;
  flex-direction: column;
  transition: box-shadow var(--transition), transform var(--transition), border-color var(--transition);
  will-change: transform;
}
.blog-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-3px);
  border-color: rgba(223,106,46,.18);
}

/* Imagen del artículo (2026-08-10): SVG propio, sangra hasta los
   bordes de la tarjeta y cierra con hairline. */
.blog-card__img {
  margin: -24px -26px 18px;
  border-bottom: 1px solid var(--gray-border);
  border-radius: calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0 0;
  overflow: hidden;
}
.blog-card__img img {
  display: block;
  width: 100%;
  height: auto;
}

.blog-card__cat {
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--orange);
  margin-bottom: 10px;
}

.blog-card h3 {
  font-size: .97rem;
  font-weight: 600;
  line-height: 1.42;
  color: var(--text-dark);
  margin-bottom: 10px;
}

.blog-card p {
  font-size: .875rem;
  color: var(--text-muted);
  line-height: 1.62;
  margin-bottom: 18px;
  flex: 1;
}

.blog-card__link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: .84rem;
  font-weight: 600;
  color: var(--orange);
  align-self: flex-start;
  transition: color var(--transition), gap var(--transition);
  /* reset button defaults */
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
  text-decoration: none;
}
.blog-card__link svg {
  transition: transform var(--transition);
}
.blog-card__link:hover {
  color: var(--orange-dark);
  gap: 8px;
}
.blog-card__link:hover svg {
  transform: translateX(2px);
}

.blog-disclaimer {
  margin-top: 28px;
  padding: 14px 18px;
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-left: 3px solid var(--gray-border);
  border-radius: var(--radius-sm);
  font-size: .8rem;
  color: var(--text-muted);
  line-height: 1.6;
  font-style: italic;
}

@media (max-width: 640px) {
  .blog-grid {
    grid-template-columns: 1fr;
  }
}


/* ═══════════════════════════════════════════════════════════
   REDES SOCIALES — bloque en contacto
   ═══════════════════════════════════════════════════════════ */
.social-follow {
  margin-top: 28px;
  padding-top: 24px;
  border-top: 1px solid var(--gray-border);
}

.social-follow__title {
  font-size: .75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--text-muted);
  margin-bottom: 7px;
}

.social-follow__text {
  font-size: .86rem;
  color: var(--text-muted);
  line-height: 1.55;
  margin-bottom: 14px;
}

.social-follow__links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.soc-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 14px;
  border-radius: 100px;
  font-size: .82rem;
  font-weight: 600;
  background: var(--gray-bg);
  color: var(--text-dark);
  border: 1px solid var(--gray-border);
  transition: background var(--transition), color var(--transition),
              border-color var(--transition), transform var(--transition);
  white-space: nowrap;
}
.soc-btn:hover {
  transform: translateY(-1px);
  background: #f0f0f0;
}

.soc-btn--linkedin {
  background: #0A66C2;
  color: var(--white);
  border-color: #0A66C2;
}
.soc-btn--linkedin:hover {
  background: #084fa0;
  border-color: #084fa0;
  color: var(--white);
}

/* ════════════════════════════════════════════════════════════
   TRAYECTORIA — LÍNEA DEL TIEMPO
   ════════════════════════════════════════════════════════════ */
.timeline-section {
  background: var(--charcoal);
  padding: var(--section-py) 0;
}

/* ── Línea vertical ── */
.timeline {
  position: relative;
  max-width: 820px;
  margin: 0 auto;
  padding-left: 36px;
}
.timeline::before {
  content: '';
  position: absolute;
  left: 10px;
  top: 6px;
  bottom: 6px;
  width: 2px;
  background: linear-gradient(180deg,
    rgba(223,106,46,0) 0%,
    rgba(223,106,46,.5) 8%,
    rgba(223,106,46,.5) 92%,
    rgba(223,106,46,0) 100%
  );
}

/* ── Ítem individual ── */
.tl-item {
  position: relative;
  margin-bottom: 28px;
}
.tl-item:last-child { margin-bottom: 0; }

/* ── Nodo naranja ── */
.tl-dot {
  position: absolute;
  left: -32px;
  top: 20px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--orange);
  box-shadow: 0 0 0 3px rgba(223,106,46,.22), 0 0 12px rgba(223,106,46,.35);
  z-index: 1;
  transition: box-shadow var(--transition), transform var(--transition);
}
.tl-item:hover .tl-dot {
  box-shadow: 0 0 0 4px rgba(223,106,46,.3), 0 0 20px rgba(223,106,46,.5);
  transform: scale(1.15);
}

/* ── Tarjeta ── */
.tl-card {
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 12px;
  overflow: hidden;
  transition: border-color var(--transition), background var(--transition);
}
.tl-card:hover {
  background: rgba(255,255,255,.06);
  border-color: rgba(223,106,46,.3);
}

/* ── Cabecera visible ── */
.tl-card__head {
  padding: 22px 24px 18px;
}

/* ── Tag de categoría ── */
.tl-tag {
  display: inline-block;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--orange);
  background: rgba(223,106,46,.12);
  border: 1px solid rgba(223,106,46,.25);
  border-radius: 100px;
  padding: 3px 10px;
  margin-bottom: 10px;
}

.tl-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--white);
  margin: 0 0 8px;
  line-height: 1.3;
}

.tl-excerpt {
  font-size: .88rem;
  color: rgba(255,255,255,.55);
  margin: 0 0 14px;
  line-height: 1.55;
}

/* ── Botón acordeón ── */
.tl-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: .82rem;
  font-weight: 600;
  color: var(--orange);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  transition: color var(--transition);
}
.tl-toggle:hover { color: var(--orange-dark); }
.tl-toggle svg {
  transition: transform .28s ease;
  flex-shrink: 0;
}
.tl-toggle[aria-expanded="true"] svg {
  transform: rotate(180deg);
}

/* ── Cuerpo expandible ── */
.tl-card__body {
  display: none;
  padding: 0 24px 22px;
  border-top: 1px solid rgba(255,255,255,.07);
  padding-top: 18px;
  animation: tl-slide-down .27s ease;
}
.tl-card__body.open {
  display: block;
}
.tl-card__body p {
  font-size: .88rem;
  color: rgba(255,255,255,.65);
  line-height: 1.65;
  margin-bottom: 12px;
}
.tl-card__body p:last-of-type { margin-bottom: 0; }
.tl-card__body h4 {
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: rgba(255,255,255,.35);
  margin: 18px 0 8px;
}

/* ── CTA dentro del cuerpo ── */
.tl-cta {
  display: inline-block;
  margin-top: 16px;
  font-size: .82rem;
  font-weight: 600;
  color: var(--orange);
  text-decoration: none;
  transition: color var(--transition);
}
.tl-cta:hover { color: var(--orange-dark); }

/* ── Disclaimer ── */
.tl-disclaimer {
  max-width: 680px;
  margin: 48px auto 0;
  text-align: center;
  font-size: .78rem;
  color: rgba(255,255,255,.3);
  line-height: 1.6;
}

/* ── Animación apertura ── */
@keyframes tl-slide-down {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── Responsive ── */
@media (max-width: 640px) {
  .timeline {
    padding-left: 28px;
  }
  .timeline::before {
    left: 7px;
  }
  .tl-dot {
    left: -24px;
    width: 12px;
    height: 12px;
    top: 22px;
  }
  .tl-card__head { padding: 18px 18px 14px; }
  .tl-card__body {
    padding: 0 18px 18px;
    padding-top: 14px;
  }
  .tl-title { font-size: .98rem; }
}

/* ════════════════════════════════════════════════════════════
   MEJORAS ESTÉTICAS — FASE 4.0
   ════════════════════════════════════════════════════════════ */

/* Jerarquía de títulos — mayor peso en secciones claras */
.solutions-section .section-header h2,
.brands-section .section-header h2,
.nosotros-section .section-header h2,
.blog-section .section-header h2 {
  font-size: clamp(1.7rem, 3.5vw, 2.3rem);
}

/* Sombra más rica en tarjetas de soluciones */
.sol-card {
  transition: transform .22s ease, box-shadow .22s ease, border-color .22s ease;
}
.sol-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 16px 40px rgba(0,0,0,.18), 0 2px 8px rgba(223,106,46,.08);
}

/* Blog cards — hover refinado */
.blog-card:hover {
  box-shadow: 0 12px 32px rgba(0,0,0,.12);
  border-color: rgba(223,106,46,.2);
}

/* Footer brand — logo con más presencia */
.footer__brand img {
  opacity: .92;
  transition: opacity var(--transition);
}
.footer__brand img:hover { opacity: 1; }

/* Reducir saturación de texto en secciones densas */
.pain-section p,
.nosotros-section p {
  line-height: 1.75;
}

/* Incremento sutil de padding en secciones de texto */
.nosotros-section,
.pain-section {
  padding-top: calc(var(--section-py) + 8px);
  padding-bottom: calc(var(--section-py) + 8px);
}

/* Credibilidad — cifras con gradiente naranja */
.stat-number, .stat-suffix {
  background: linear-gradient(135deg, var(--orange) 0%, #f0803f 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  color: var(--orange); /* fallback */
}

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

/* ════════════════════════════════════════════════════════════
   MARCA DE AGUA — ISOLOGO DATATELL
   ════════════════════════════════════════════════════════════ */

/* Hero — isologo como marca de agua bottom-right */
.hero__watermark {
  position: absolute;
  bottom: -30px;
  right: -50px;
  width: 360px;
  height: auto;
  opacity: .045;
  pointer-events: none;
  user-select: none;
  z-index: 0;
  flex-shrink: 0;
}

@media (max-width: 768px) {
  .hero__watermark {
    width: 200px;
    bottom: -10px;
    right: -20px;
    opacity: .03;
  }
}

/* ════════════════════════════════════════════════════════════
   ACENTOS DE SECCIÓN — LÍNEA NARANJA SUPERIOR
   ════════════════════════════════════════════════════════════ */

/* Todas las secciones oscuras reciben un acento naranja top */
.timeline-section,
.experience-section,
.credibility-section {
  position: relative;
  overflow: hidden;
}

.timeline-section::before,
.experience-section::before,
.credibility-section::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(223,106,46,.35) 15%,
    var(--orange) 50%,
    rgba(223,106,46,.35) 85%,
    transparent 100%
  );
  z-index: 1;
  pointer-events: none;
}

/* Timeline — la marca de agua del isologo se RETIRA el 2026-08-26 por
   decisión de Julián: en pantallas grandes el recorte quedaba a la
   derecha como una mancha diagonal que competía con las tarjetas de la
   línea de tiempo y se leía como un error de imagen, no como textura.
   Se deja el bloque comentado y no borrado, con sus valores originales,
   por si se quisiera recuperar con otro encuadre.

.timeline-section::after {
  content: '';
  position: absolute;
  top: -30px;
  right: -40px;
  width: 280px;
  height: 290px;
  background: url('assets/isologo-datatell.png') center / cover no-repeat;
  opacity: .03;
  pointer-events: none;
  z-index: 0;
}
*/

/* ════════════════════════════════════════════════════════════
   FOOTER — logo naranja
   ════════════════════════════════════════════════════════════ */
.footer__brand img {
  display: block;
  filter: none; /* naranja nativo, sin ajuste */
}

/* ════════════════════════════════════════════════════════════
   MODAL — RECURSOS TÉCNICOS
   ════════════════════════════════════════════════════════════ */
.rec-modal {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.rec-modal[hidden] { display: none; }

.rec-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 10, 10, .72);
  backdrop-filter: blur(3px);
}

.rec-modal__box {
  position: relative;
  background: #fff;
  border-radius: 16px;
  padding: 2.5rem 2rem 2rem;
  max-width: 560px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: 0 24px 64px rgba(0,0,0,.28);
  animation: rec-modal-in .22s ease;
}
@keyframes rec-modal-in {
  from { opacity: 0; transform: translateY(20px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

.rec-modal__close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--gray-500, #6b7280);
  padding: .35rem;
  border-radius: 6px;
  display: flex;
  align-items: center;
  transition: color .15s, background .15s;
}
.rec-modal__close:hover {
  color: var(--navy, #0f1f3d);
  background: #f3f4f6;
}

.rec-modal__cat {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--orange, #df6a2e);
  margin: 0 0 .6rem;
}

.rec-modal__title {
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--navy, #0f1f3d);
  line-height: 1.35;
  margin: 0 0 1.4rem;
}

.rec-modal__list {
  list-style: none;
  padding: 0;
  margin: 0 0 2rem;
  display: flex;
  flex-direction: column;
  gap: .75rem;
}
.rec-modal__list li {
  padding-left: 1.4rem;
  position: relative;
  color: #374151;
  font-size: .95rem;
  line-height: 1.55;
}
.rec-modal__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .55em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--orange, #df6a2e);
}

.rec-modal__cta {
  display: inline-flex;
  text-decoration: none;
}

@media (max-width: 480px) {
  .rec-modal__box {
    padding: 2rem 1.25rem 1.5rem;
  }
  .rec-modal__title {
    font-size: 1.05rem;
  }
}

/* ════════════════════════════════════════════════════════════
   FORM LOADER — spinner naranja centrado en el formulario
   ════════════════════════════════════════════════════════════ */
.form-loader {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: .75rem 0 .25rem;
}
.form-loader[hidden] { display: none; }

.form-loader__ring {
  display: block;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 3px solid rgba(223, 106, 46, .18);
  border-top-color: #df6a2e;
  animation: dt-ring-spin .75s linear infinite;
}

@keyframes dt-ring-spin {
  to { transform: rotate(360deg); }
}

/* ════════════════════════════════════════════════════════════
   MEJORAS VISUALES — Secciones claras
   ════════════════════════════════════════════════════════════ */

/* ── 1. Patrón puntillado técnico en secciones blancas ──── */
.pain-section,
.solutions-section,
.responsibility-section {
  background-image: radial-gradient(circle, rgba(223,106,46,.058) 1.5px, transparent 1.5px);
  background-size: 32px 32px;
  background-color: var(--white);
}

/* ── 2. Acento naranja bajo h2 en secciones blancas ─────── */
.pain-section .section-header h2::after,
.solutions-section .section-header h2::after,
.responsibility-text h2::after {
  content: '';
  display: block;
  width: 40px;
  height: 3px;
  background: var(--orange);
  border-radius: 2px;
  margin-top: 14px;
}

/* ── 3. Iconos más grandes y expresivos ─────────────────── */
.pain-card__icon,
.solution-card__icon {
  width: 60px;
  height: 60px;
  border-radius: var(--radius);
  background: rgba(223,106,46,.09);
  border: 1.5px solid rgba(223,106,46,.14);
  transition: background var(--transition), border-color var(--transition), transform .25s var(--ease-spring);
}
.pain-card__icon svg,
.solution-card__icon svg {
  width: 30px;
  height: 30px;
}

/* ── 4. Sombra de reposo sutil en pain-card / solution-card */
.pain-card,
.solution-card {
  box-shadow: 0 1px 4px rgba(0,0,0,.06);
}

/* ── 5. Hover pain-card: elevación + borde naranja ──────── */
.pain-card:hover {
  box-shadow: 0 10px 32px rgba(0,0,0,.11), 0 2px 8px rgba(223,106,46,.08);
  border-color: rgba(223,106,46,.22);
  transform: translateY(-4px);
}
.pain-card:hover .pain-card__icon {
  background: rgba(223,106,46,.16);
  border-color: rgba(223,106,46,.3);
  transform: scale(1.06);
}

/* ── 6. Solution card: nodo de esquina + barra parcial ──── */
.solution-card::after {
  content: '';
  position: absolute;
  top: 18px;
  right: 18px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(223,106,46,.2);
  border: 1.5px solid rgba(223,106,46,.35);
  transition: background var(--transition), border-color var(--transition), transform var(--transition);
}
.solution-card:hover::after {
  background: var(--orange);
  border-color: var(--orange);
  transform: scale(1.25);
}
.solution-card::before {
  height: 3px;
  transform: scaleX(0.22);
  opacity: .32;
  transition: transform 280ms var(--ease), opacity 280ms var(--ease);
}
.solution-card:hover::before {
  transform: scaleX(1);
  opacity: 1;
}
.solution-card:hover {
  box-shadow: 0 10px 32px rgba(0,0,0,.11), 0 2px 8px rgba(223,106,46,.08);
  border-color: rgba(223,106,46,.18);
  transform: translateY(-4px);
}
.solution-card:hover .solution-card__icon {
  background: rgba(223,106,46,.16);
  border-color: rgba(223,106,46,.3);
  transform: scale(1.06);
}

/* ── 7. Blog cards: borde izquierdo naranja tipo nodo ───── */
.blog-card {
  box-shadow: inset 3px 0 0 rgba(223,106,46,.15), 0 1px 4px rgba(0,0,0,.05);
}
.blog-card:hover {
  box-shadow: inset 3px 0 0 var(--orange), 0 10px 28px rgba(0,0,0,.10);
  border-color: rgba(223,106,46,.18);
  transform: translateY(-3px);
}

/* ── 8. Brands section: cuadrícula técnica sutil ────────── */
.brands-section {
  background-image:
    linear-gradient(rgba(0,0,0,.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0,0,0,.03) 1px, transparent 1px);
  background-size: 40px 40px;
  background-color: var(--gray-bg);
}
.brand-item:hover {
  border-color: rgba(223,106,46,.25);
  box-shadow: 0 4px 16px rgba(223,106,46,.07), 0 1px 4px rgba(0,0,0,.06);
  transform: translateY(-2px);
}

/* ── ajuste: cuadrícula marcas con opacidad reducida ─────── */
.brands-section {
  background-image:
    linear-gradient(rgba(0,0,0,.018) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0,0,0,.018) 1px, transparent 1px);
}

/* ── 9. Acento h2 en secciones grises ───────────────────── */
.brands-section .section-header h2::after,
.blog-section .section-header h2::after {
  content: '';
  display: block;
  width: 40px;
  height: 3px;
  background: var(--orange);
  border-radius: 2px;
  margin-top: 14px;
}

/* ═══════════════════════════════════════════════════════════
   VISUAL LAYER 2 — apoyo adicional en secciones blancas
   ═══════════════════════════════════════════════════════════ */

/* Necesario para posicionar decoraciones absolutas */
.pain-section,
.solutions-section,
.responsibility-section,
.blog-section {
  position: relative;
}

/* Glow ambiental — esquina superior derecha (pain) */
.pain-section::before {
  content: '';
  position: absolute;
  top: -60px; right: -60px;
  width: 420px; height: 320px;
  background: radial-gradient(ellipse at 100% 0%, rgba(223,106,46,.05) 0%, transparent 65%);
  pointer-events: none;
}

/* Glow ambiental — esquina superior izquierda (solutions) */
.solutions-section::before {
  content: '';
  position: absolute;
  top: -60px; left: -60px;
  width: 420px; height: 320px;
  background: radial-gradient(ellipse at 0% 0%, rgba(223,106,46,.045) 0%, transparent 65%);
  pointer-events: none;
}

/* Cluster de nodos — esquina inferior derecha (pain) */
.pain-section::after {
  content: '';
  position: absolute;
  bottom: 48px; right: 48px;
  width: 90px; height: 90px;
  background-image: radial-gradient(circle, rgba(223,106,46,.22) 1.5px, transparent 1.5px);
  background-size: 14px 14px;
  pointer-events: none;
}

/* Cluster de nodos — esquina inferior izquierda (solutions) */
.solutions-section::after {
  content: '';
  position: absolute;
  bottom: 48px; left: 48px;
  width: 90px; height: 90px;
  background-image: radial-gradient(circle, rgba(223,106,46,.18) 1.5px, transparent 1.5px);
  background-size: 14px 14px;
  pointer-events: none;
}

/* Cluster de nodos — esquina superior derecha (responsibility) */
.responsibility-section::after {
  content: '';
  position: absolute;
  top: 56px; right: 48px;
  width: 76px; height: 76px;
  background-image: radial-gradient(circle, rgba(223,106,46,.18) 1.5px, transparent 1.5px);
  background-size: 14px 14px;
  pointer-events: none;
}

/* Cluster de nodos — esquina superior derecha (blog) */
.blog-section::after {
  content: '';
  position: absolute;
  top: 56px; right: 48px;
  width: 76px; height: 76px;
  background-image: radial-gradient(circle, rgba(223,106,46,.15) 1.5px, transparent 1.5px);
  background-size: 14px 14px;
  pointer-events: none;
}

/* Patrón sutil en sección formulario (fondo gris) */
.form-section {
  background-image: radial-gradient(circle, rgba(15,36,64,.042) 1.5px, transparent 1.5px);
  background-size: 32px 32px;
}

/* Línea superior naranja degradada en sección contacto */
.form-section::before {
  content: '';
  display: block;
  height: 3px;
  background: linear-gradient(90deg, transparent 0%, var(--orange) 30%, var(--orange) 70%, transparent 100%);
  opacity: .35;
}

/* ═══════════════════════════════════════════════════════════
   BRAND ITEMS — button reset + interactividad
   ═══════════════════════════════════════════════════════════ */
button.brand-item {
  appearance: none;
  font: inherit;
  text-align: inherit;
  cursor: pointer;
  padding-bottom: 28px; /* espacio para el hint */
}
button.brand-item:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 2px;
}

.brand-item__hint {
  position: absolute;
  bottom: 7px;
  left: 0; right: 0;
  text-align: center;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--orange);
  opacity: 0;
  transform: translateY(3px);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
  pointer-events: none;
}
.brand-item:hover .brand-item__hint,
.brand-item:focus-visible .brand-item__hint {
  opacity: 1;
  transform: translateY(0);
}

/* ═══════════════════════════════════════════════════════════
   BRAND MODAL — extensión del estilo rec-modal
   ═══════════════════════════════════════════════════════════ */
.brand-modal__box {
  max-width: 600px;
}

.brand-modal__logo-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  margin-bottom: 20px;
  padding: 8px 0;
}
.brand-modal__logo {
  max-height: 44px;
  max-width: 180px;
  width: auto;
  object-fit: contain;
  filter: none;
  opacity: 1;
}

.brand-modal__desc {
  color: var(--text-muted);
  font-size: 0.96rem;
  line-height: 1.68;
  margin-bottom: 24px;
  margin-top: -4px;
}

.brand-modal__lists {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin-bottom: 28px;
}
@media (max-width: 540px) {
  .brand-modal__lists { grid-template-columns: 1fr; }
  .brand-modal__box   { padding: 28px 20px; }
}

.brand-modal__label {
  font-size: 0.74rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--orange);
  margin-bottom: 10px;
}

/* ═══════════════════════════════════════════════════════════
   FIX OVERFLOW + INTENSIFICAR PATRONES (v3)
   ═══════════════════════════════════════════════════════════ */

/* 1 · Red global para overflow horizontal ─────────────────── */
html,
body {
  overflow-x: hidden;
  max-width: 100%;
}

/* 2 · Contener pseudo-elementos que se salen en mobile ─────── */
.pain-section,
.solutions-section {
  overflow: hidden;
}

/* 3 · Intensificar dot pattern en secciones blancas ────────── */
/* (sobreescribe el valor anterior: .058 → .10, 1.5px → 2px, 32px → 28px) */
.pain-section,
.solutions-section,
.responsibility-section {
  background-image: radial-gradient(circle, rgba(223,106,46,.10) 2px, transparent 2px);
  background-size: 28px 28px;
}

/* 4 · Intensificar dot pattern en form section ─────────────── */
.form-section {
  background-image: radial-gradient(circle, rgba(15,36,64,.072) 2px, transparent 2px);
  background-size: 28px 28px;
}

/* 5 · Intensificar cuadrícula en sección de marcas ─────────── */
/* Sobreescribe los dos bloques anteriores con valor más visible */
.brands-section {
  background-image:
    linear-gradient(rgba(0,0,0,.032) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0,0,0,.032) 1px, transparent 1px);
  background-size: 36px 36px;
}

/* 6 · Intensificar ambient glows de esquinas ───────────────── */
.pain-section::before {
  background: radial-gradient(ellipse at 100% 0%, rgba(223,106,46,.08) 0%, transparent 65%);
}
.solutions-section::before {
  background: radial-gradient(ellipse at 0% 0%, rgba(223,106,46,.072) 0%, transparent 65%);
}

/* 7 · Intensificar node clusters — puntos más grandes ──────── */
.pain-section::after {
  background-image: radial-gradient(circle, rgba(223,106,46,.32) 2px, transparent 2px);
  background-size: 12px 12px;
  width: 110px;
  height: 110px;
}
.solutions-section::after {
  background-image: radial-gradient(circle, rgba(223,106,46,.28) 2px, transparent 2px);
  background-size: 12px 12px;
  width: 110px;
  height: 110px;
}
.responsibility-section::after {
  background-image: radial-gradient(circle, rgba(223,106,46,.26) 2px, transparent 2px);
  background-size: 12px 12px;
  width: 88px;
  height: 88px;
}
.blog-section::after {
  background-image: radial-gradient(circle, rgba(223,106,46,.22) 2px, transparent 2px);
  background-size: 12px 12px;
  width: 88px;
  height: 88px;
}

/* ═══════════════════════════════════════════════════════════
   ETAPA 1 — PRECISION INFRASTRUCTURE
   ═══════════════════════════════════════════════════════════ */

/* ── 1. Thumbnails técnicos en Experiencia en acción ─────── */
.exp-thumb__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ── 2. Hero: textura diagonal del isologo ────────────────── */
/* Líneas en diagonal a ~-42° (ángulo de las barras del isologo)
   implementadas como background-image, siempre detrás del contenido */
.hero {
  background-image: repeating-linear-gradient(
    48deg,
    transparent       0px,
    transparent      16px,
    rgba(223,106,46,.022) 16px,
    rgba(223,106,46,.022) 28px,
    transparent      28px,
    transparent      44px,
    rgba(255,255,255,.007) 44px,
    rgba(255,255,255,.007) 54px
  );
}

/* ── 3. CTA Intermedio: textura del isologo sobre naranja ─── */
.cta-mid {
  background-image: repeating-linear-gradient(
    48deg,
    transparent        0px,
    transparent       16px,
    rgba(255,255,255,.042) 16px,
    rgba(255,255,255,.042) 26px,
    transparent       26px,
    transparent       44px,
    rgba(0,0,0,.014)  44px,
    rgba(0,0,0,.014)  54px
  );
}

/* ── 4. Intensificar dot pattern en secciones blancas ──────── */
/* .10 → .12 — más visible sin convertirse en ruido */
.pain-section,
.solutions-section,
.responsibility-section {
  background-image: radial-gradient(circle, rgba(223,106,46,.12) 2px, transparent 2px);
  background-size: 28px 28px;
}

/* ── 5. Intensificar dot pattern en formulario ──────────────── */
.form-section {
  background-image: radial-gradient(circle, rgba(15,36,64,.085) 2px, transparent 2px);
  background-size: 28px 28px;
}

/* ── 6. Intensificar cuadrícula en sección marcas ───────────── */
.brands-section {
  background-image:
    linear-gradient(rgba(0,0,0,.038) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0,0,0,.038) 1px, transparent 1px);
  background-size: 36px 36px;
}

/* ── 7. Contener pseudo-elementos en secciones adicionales ──── */
/* Previene cualquier desbordamiento lateral en mobile */
.responsibility-section,
.blog-section {
  overflow: hidden;
}

/* ═══════════════════════════════════════════════════════════
   ETAPA 2 — DESIGN SYSTEM UPGRADE (IBM Plex + tokens)
   ═══════════════════════════════════════════════════════════ */

/* Stat numbers en IBM Plex Mono — se leen como datos técnicos */
.stat-number,
.stat-suffix {
  font-family: var(--font-mono);
  letter-spacing: var(--ls-tight);
}

/* Stats: bordes más visibles (.06 → .12) */
.stat-item {
  border-color: rgba(255,255,255,.12);
}

/* Pain cards: top edge accent naranja en hover */
.pain-card:hover {
  box-shadow: var(--shadow-md), inset 0 2px 0 0 var(--orange);
}

/* Exp cards: borde más visible en dark (.07 → .14) */
.exp-card {
  border-color: rgba(255,255,255,.12);
}

/* Solution card: top bar siempre visible a baja opacidad */
.solution-card::before {
  transform: scaleX(.28);
  opacity: .45;
}
.solution-card:hover::before {
  transform: scaleX(1);
  opacity: 1;
}

/* Highlight quote: refinamiento con mono label */
.highlight-quote {
  background: rgba(223,106,46,.07);
  border-left-width: 2px;
}

/* Section-header sub con line-height relaxed */
.section-header p {
  line-height: 1.65;
  font-size: 1.05rem;
}

/* Navbar: font-weight 500 en los links — más legible */
.nav-link {
  font-weight: 500;
}

/* Botones: tracking ligeramente más amplio */
.btn {
  letter-spacing: 0.01em;
}

/* Eyebrow en secciones oscuras: mantiene estilo mono */
.nosotros-section .eyebrow,
.experience-section .eyebrow,
.cta-section .eyebrow {
  font-family: var(--font-mono);
  letter-spacing: var(--ls-eyebrow);
  opacity: .82;
}

/* ═══════════════════════════════════════════════════════════
   SECCIÓN IA PRIVADA ON-PREMISE
   ═══════════════════════════════════════════════════════════ */

.ia-section {
  background: var(--gray-bg);
  padding: var(--section-py) 0;
}

.ia-eyebrow {
  display: inline-block;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--orange);
  margin-bottom: 18px;
  font-family: var(--font-mono);
}

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

.ia-steps {
  display: grid;
  gap: 24px;
  grid-template-columns: 1fr;
  margin-top: 52px;
  padding-top: 44px;
  border-top: 1px solid var(--gray-border);
}
@media (min-width: 768px) {
  .ia-steps { grid-template-columns: repeat(3, 1fr); gap: 36px; }
}

.ia-step__num {
  display: block;
  font-family: var(--font-mono);
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--orange);
  line-height: 1;
  margin-bottom: 14px;
}
.ia-step h4 {
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--text-dark);
  margin-bottom: 8px;
  line-height: 1.35;
}
.ia-step p {
  color: var(--text-muted);
  font-size: .94rem;
  line-height: 1.65;
}

.ia-cta {
  margin-top: 52px;
  padding: 30px 32px;
  background: var(--charcoal);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  gap: 20px;
  align-items: flex-start;
}
@media (min-width: 860px) {
  .ia-cta {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 32px;
  }
}
.ia-cta__text {
  color: rgba(255, 255, 255, .82);
  font-size: .98rem;
  line-height: 1.65;
  margin: 0;
  max-width: 640px;
}
.ia-cta__text strong { color: var(--white); font-weight: 600; }
.ia-cta .btn { flex-shrink: 0; }

/* ─── Maqueta de consulta documental (ejemplo ilustrativo) ───
   Filas de hoja de datos con hairlines de 1 px, no burbujas. */
.ia-demo {
  margin: 44px auto 56px;
  max-width: 780px;
}
.ia-demo__kicker {
  font-family: var(--font-mono);
  font-size: .78rem;
  letter-spacing: .04em;
  color: var(--text-muted);
  margin-bottom: 14px;
}
.ia-demo__panel {
  margin: 0;
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-radius: 2px;
}
.ia-demo__bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 18px;
  background: var(--charcoal);
  color: rgba(255,255,255,.82);
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .08em;
}
.ia-demo__status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--white);
  white-space: nowrap;
}
.ia-demo__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--orange);
  flex-shrink: 0;
}
.ia-demo__body { margin: 0; }
.ia-demo__msg {
  display: grid;
  grid-template-columns: 118px 1fr;
  gap: 16px;
  padding: 18px;
  border-top: 1px solid var(--gray-border);
}
.ia-demo__msg:first-child { border-top: none; }
.ia-demo__msg--user { background: var(--gray-bg); }
.ia-demo__who {
  font-family: var(--font-mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--gray-light);
  padding-top: 3px;
}
.ia-demo__who--ai { color: var(--orange); }
.ia-demo__msg dd { margin: 0; min-width: 0; }
.ia-demo__msg p {
  font-size: .94rem;
  line-height: 1.65;
  color: var(--text-body);
}
.ia-demo__msg--user p { color: var(--text-dark); font-weight: 500; }
.ia-demo__sources {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}
.ia-demo__src {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--gray-border);
  border-radius: 2px;
  font-family: var(--font-mono);
  font-size: .7rem;
  color: var(--text-muted);
  word-break: break-word;
}
.ia-demo__src svg { flex-shrink: 0; color: var(--orange); }
.ia-demo__note {
  padding: 12px 18px;
  border-top: 1px solid var(--gray-border);
  font-size: .78rem;
  line-height: 1.55;
  color: var(--gray-light);
}
@media (max-width: 640px) {
  .ia-demo { margin: 36px auto 44px; }
  .ia-demo__msg {
    grid-template-columns: 1fr;
    gap: 6px;
    padding: 14px 16px;
  }
  .ia-demo__who { padding-top: 0; }
  .ia-demo__msg p { font-size: .9rem; }
}


/* ═══════════════════════════════════════════════════════════
   HERO TAGLINE
   ═══════════════════════════════════════════════════════════ */
.hero__tagline {
  font-size: .95rem;
  color: rgba(255, 255, 255, .58);
  letter-spacing: var(--ls-tight);
  margin: 0;
  font-style: italic;
}


/* ═══════════════════════════════════════════════════════════
   CRED STRIP
   ═══════════════════════════════════════════════════════════ */
.cred-strip {
  background: var(--off-white, #F7F7F5);
  padding: 52px 0;
  border-top: 1px solid rgba(0,0,0,.07);
  border-bottom: 1px solid rgba(0,0,0,.07);
}

.cred-strip__list {
  display: flex;
  flex-wrap: wrap;
  gap: 40px 60px;
  list-style: none;
  margin: 0;
  padding: 0;
  justify-content: center;
}

.cred-strip__item {
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: center;
}

.cred-strip__value {
  font-family: var(--font-mono);
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--charcoal);
  letter-spacing: var(--ls-tight);
}

.cred-strip__label {
  font-size: .88rem;
  color: rgba(17,17,17,.55);
  letter-spacing: var(--ls-tight);
}

@media (min-width: 768px) {
  .cred-strip__list {
    flex-wrap: nowrap;
    justify-content: space-between;
  }
  .cred-strip__item { text-align: left; }
}


/* ═══════════════════════════════════════════════════════════
   SECTORES
   ═══════════════════════════════════════════════════════════ */
.sectores-section {
  background: var(--white);
  padding: 96px 0;
}

.sectores-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 32px;
  margin-top: 56px;
}

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

.sector-card {
  background: var(--off-white, #F7F7F5);
  border: 1px solid rgba(0,0,0,.09);
  border-radius: 4px;
  padding: 40px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.sector-card__eyebrow {
  font-family: var(--font-mono);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--orange);
}

.sector-card__title {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--charcoal);
  letter-spacing: var(--ls-tight);
  line-height: 1.45;
  margin: 0;
}

.sector-card__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sector-card__list li {
  font-size: .93rem;
  color: rgba(17,17,17,.72);
  padding-left: 18px;
  position: relative;
  letter-spacing: var(--ls-tight);
}

.sector-card__list li::before {
  content: '—';
  position: absolute;
  left: 0;
  color: var(--orange);
  font-weight: 600;
}

.sector-card__note {
  font-size: .88rem;
  color: rgba(17,17,17,.55);
  border-top: 1px solid rgba(0,0,0,.09);
  padding-top: 16px;
  margin: 0;
  letter-spacing: var(--ls-tight);
  line-height: 1.65;
}


/* ═══════════════════════════════════════════════════════════
   DEL DIAGNÓSTICO AL ACOMPAÑAMIENTO
   ═══════════════════════════════════════════════════════════ */
.diagnostico-section {
  /* var(--navy) no existe desde el rediseño: caía a fondo claro y el
     texto blanco de las tarjetas quedaba invisible (bug 2026-08-10). */
  background: var(--charcoal);
  padding: 96px 0;
}

.diagnostico-section .section-header h2,
.diagnostico-section .section-header p {
  color: var(--white);
}

.diagnostico-section .section-header p {
  color: rgba(255,255,255,.72);
}

.cards-grid--diagnostico {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
  margin-top: 56px;
}

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

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

.diagnostico-card {
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 4px;
  padding: 32px;
  position: relative;
}

.diagnostico-card h3 {
  color: var(--white);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: var(--ls-tight);
  margin: 0 0 10px;
}

.diagnostico-card p {
  color: rgba(255,255,255,.68);
  font-size: .9rem;
  line-height: 1.65;
  margin: 0;
  letter-spacing: var(--ls-tight);
}

.diagnostico-card__num {
  font-family: var(--font-mono);
  font-size: 2rem;
  font-weight: 600;
  color: var(--orange);
  opacity: .55;
  line-height: 1;
  margin-bottom: 20px;
  letter-spacing: var(--ls-tight);
}

.diagnostico-section .ia-eyebrow {
  color: var(--orange);
  border-color: var(--orange);
}


/* ═══════════════════════════════════════════════════════════
   NOSOTROS
   ═══════════════════════════════════════════════════════════ */
.nosotros-section {
  background: var(--white);
  padding: 96px 0;
  border-top: 1px solid rgba(0,0,0,.07);
}

.nosotros-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 56px;
  align-items: start;
}

@media (min-width: 900px) {
  .nosotros-layout {
    grid-template-columns: 1fr 360px;
    gap: 80px;
  }
}

.nosotros-text .eyebrow {
  font-family: var(--font-mono);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--orange);
  display: block;
  margin-bottom: 16px;
}

.nosotros-text h2 {
  font-size: clamp(1.6rem, 3.5vw, 2.2rem);
  font-weight: 700;
  letter-spacing: var(--ls-tight);
  color: var(--charcoal);
  margin: 0 0 24px;
  line-height: 1.2;
}

.nosotros-text p {
  font-size: 1rem;
  color: rgba(17,17,17,.72);
  line-height: 1.75;
  letter-spacing: var(--ls-tight);
  margin: 0 0 16px;
}

.nosotros-quote {
  border-left: 3px solid var(--orange);
  padding: 12px 20px;
  margin: 28px 0;
  font-size: 1.05rem;
  font-style: italic;
  color: var(--charcoal);
  font-weight: 500;
  letter-spacing: var(--ls-tight);
  line-height: 1.55;
}

.nosotros-facts {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.nosotros-fact {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-bottom: 32px;
  border-bottom: 1px solid rgba(0,0,0,.08);
}

.nosotros-fact:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.nosotros-fact__value {
  font-family: var(--font-mono);
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--charcoal);
  letter-spacing: var(--ls-tight);
}

.nosotros-fact__label {
  font-size: .88rem;
  color: rgba(17,17,17,.55);
  letter-spacing: var(--ls-tight);
}

/* ══════════════════════════════════════════════════════════════════════
   CAPA DE SISTEMA VISUAL · 2026-08-06
   ──────────────────────────────────────────────────────────────────────
   Refinamiento sobre la base existente, sin reescribirla. Va al final a
   propósito: mismas especificidades, gana por orden. Para revertir, se
   borra este bloque completo y el sitio vuelve exactamente a como estaba.
   Respaldo íntegro en _respaldo/styles.css.antes-de-sistema-visual-2026-08-06

   Cuatro cosas, en este orden de impacto:
     1. Escala tipográfica de cuatro peldaños reales
     2. Espaciado de sección con sistema (dos densidades)
     3. Jerarquía de color explícita + naranja que pasa AA en texto
     4. Aire dentro de las tarjetas
   ══════════════════════════════════════════════════════════════════════ */

:root {
  /* ── 1. Escala tipográfica ──
     El problema medido: h3 estaba en 1.05rem (16.8px) contra un cuerpo de
     16.8px. Los subtítulos eran del mismo tamaño que el texto que titulan,
     así que las secciones largas se leían como un muro plano.
     Cuatro peldaños con separación real: 56 / 40 / 24 / 16.8 */
  --fs-h1:    clamp(2.25rem, 4.6vw, 3.5rem);   /* 36 → 56 */
  --fs-h2:    clamp(1.75rem, 3.2vw, 2.5rem);   /* 28 → 40 */
  --fs-h3:    clamp(1.2rem, 1.5vw, 1.5rem);    /* 19 → 24  ← el arreglo clave */
  --fs-h4:    1.0625rem;                       /* 17 */
  --fs-body:  1.05rem;                         /* 16.8 */
  --fs-small: .875rem;                         /* 14 */

  /* ── 2. Espaciado ──
     Antes había cinco valores de padding de sección sin base común
     (52 / 72 / 88 / 96 / 120). Ahora dos densidades y nada más. */
  --section-py:    96px;
  --section-py-lg: 128px;
  --section-py-sm: 64px;

  /* ── 3. Color ──
     El naranja de marca da 3.37:1 sobre blanco: no pasa AA (4.5) para
     texto normal. Este mantiene el tono (20.3°) y la saturación exactos,
     solo baja la luminosidad hasta 4.61:1. Se usa SOLO en texto y enlaces;
     los iconos, barras y números grandes conservan el naranja original. */
  --orange-text: #C0551D;
}

/* ── 1. Tipografía ─────────────────────────────────────────────────── */
h1 { font-size: var(--fs-h1); line-height: 1.1;  letter-spacing: -.025em; }
h2 { font-size: var(--fs-h2); line-height: 1.16; letter-spacing: -.02em; }
h3 {
  font-size: var(--fs-h3);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -.011em;
}
h4 { font-size: var(--fs-h4); font-weight: 600; line-height: 1.35; }

/* Un poco de aire bajo los títulos: sin esto el peldaño nuevo se pega al
   párrafo que sigue y el tamaño extra se lee como apretado, no como jerarquía. */
h2 { margin-bottom: 20px; }
h3 { margin-bottom: 10px; }

/* ── 2. Espaciado de sección ───────────────────────────────────────── */
.cred-strip       { padding: var(--section-py-sm) 0; }   /* era 52px */
.responsibility-section,
.cta-mid          { padding: var(--section-py) 0; }      /* era 72px */
.sectores-section { padding: var(--section-py) 0; }
.hero             { padding: var(--section-py-lg) 0 var(--section-py) 0; }

/* Aire entre el encabezado de sección y su contenido */
.section-header { margin-bottom: 48px; }

/* ── 3. Jerarquía de color ─────────────────────────────────────────────
   Primario   #111111  títulos            18.9:1
   Secundario #3C3C3C  cuerpo             11.0:1
   Terciario  #6B6B6B  notas y metadatos   5.3:1
   Acento     #C0551D  enlaces y eyebrows  4.6:1
   El gris #9A9A9A (2.81:1) deja de usarse para texto sobre fondo claro. */

/* Texto chico y enlaces: pasan a naranja accesible */
.eyebrow,
.eyebrow--dark,
.ia-eyebrow,
.sector-card__eyebrow,
.nosotros-text .eyebrow,
.diagnostico-section .ia-eyebrow,
.btn--white,
.req,
.text-link,
.ctx-cta__link,
.blog-card__cat,
.blog-card__link,
.tl-tag,
.tl-toggle,
.tl-cta,
.brand-item__hint,
.brand-modal__label { color: var(--orange-text); }

/* Botones sólidos: con el naranja original el texto blanco encima daba
   3.37:1. Con este pasa AA sin cambiar la identidad de marca. */
.btn--primary,
.btn--soporte {
  background: var(--orange-text);
  border-color: var(--orange-text);
}
.btn--primary:hover,
.btn--soporte:hover {
  background: #A84815;
  border-color: #A84815;
}

/* Terciario legible: el gris claro no alcanzaba para texto sobre blanco */
.form-note,
.hero__note { color: var(--text-muted); }

/* ── 4. Aire en las tarjetas ───────────────────────────────────────────
   Buena parte de la sensación de "denso" no era el estilo sino la falta
   de respiro dentro de cada tarjeta. */
.pain-card,
.solution-card,
.sector-card,
.blog-card,
.diagnostico-card { padding: 32px 28px; }

.pain-card p,
.solution-card p,
.sector-card p    { margin-top: 10px; }

/* La tagline del hero estaba pegada al botón, sin respiro */
.hero__tagline { margin-bottom: 20px; }

/* ══════════════════════════════════════════════════════════════════════
   SECCIÓN "CLIENTES" — placeholders deliberados
   ──────────────────────────────────────────────────────────────────────
   Mismo tratamiento visual que el carrusel de fabricantes, para que se
   lea como un espacio reservado a propósito y no como una imagen que no
   cargó. Cuando lleguen los logotipos autorizados, cada .client-slot se
   reemplaza por un <img> y se borra la clase --empty.
   ══════════════════════════════════════════════════════════════════════ */
.clients-section { padding: var(--section-py) 0; background: var(--gray-bg); }

.clients-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  align-items: center;
}
@media (min-width: 540px)  { .clients-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 860px)  { .clients-grid { grid-template-columns: repeat(4, 1fr); gap: 20px; } }

.client-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 20px 16px;
  min-height: 96px;
  background: var(--white);
  border: 1px dashed var(--gray-border);
  border-radius: var(--radius);
}
.client-slot__label {
  font-family: var(--font-mono);
  font-size: .68rem;
  line-height: 1.5;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--gray-light);
}
.clients-note {
  margin-top: 24px;
  font-size: var(--fs-small);
  color: var(--text-muted);
}

/* ── Corrección: títulos de tarjeta ────────────────────────────────────
   Seis reglas de clase fijaban los h3 de tarjeta en 1rem / .97rem — por
   debajo del cuerpo (1.05rem). Eran los títulos que más aplanaban la
   lectura, y ganaban por especificidad sobre la regla `h3` de arriba.
   Se les da su propio peldaño: por encima del cuerpo, por debajo de un
   título de subsección. Escala completa: 56 / 40 / 24 / 20 / 16.8 */
:root { --fs-card-title: 1.25rem; }   /* 20px */

.pain-card h3,
.solution-card h3,
.exp-card__body h3,
.blog-card h3,
.diagnostico-card h3 {
  font-size: var(--fs-card-title);
  font-weight: 700;
  line-height: 1.32;
  letter-spacing: -.011em;
}

/* Última densidad suelta: estas dos secciones usaban section-py + 8px,
   que reintroducía un valor fuera de la escala (104px). */
.nosotros-section,
.pain-section {
  padding-top: var(--section-py);
  padding-bottom: var(--section-py);
}

/* ── Densidad en móvil ──────────────────────────────────────────────────
   El aire nuevo es correcto en desktop, pero en pantalla chica se paga
   en scroll: con el mismo padding la página creció ~2.200 px. Acá se
   recupera parte sin tocar la respiración del escritorio. */
@media (max-width: 639px) {
  .hero { padding: var(--section-py) 0 var(--section-py-sm); }

  .pain-card,
  .solution-card,
  .sector-card,
  .blog-card,
  .diagnostico-card { padding: 26px 22px; }

  .section-header { margin-bottom: 32px; }

  .client-slot { min-height: 84px; }
}

/* ══════════════════════════════════════════════════════════════════════
   CAPA DE REDISEÑO · 2026-08-08
   ──────────────────────────────────────────────────────────────────────
   Home corta + páginas internas. Va al final a propósito: gana por orden
   sin reescribir la base. Para revertir, borrar este bloque y restaurar
   los archivos de _respaldo/*.antes-de-rediseno-2026-08-08.
   Decisiones y su trazabilidad contra la competencia:
   _notas/decisiones-rediseno-2026-08-08.md
   ══════════════════════════════════════════════════════════════════════ */

:root {
  /* Escala tipográfica un peldaño arriba: el estándar internacional
     (WWT, Presidio, Computacenter) titula grande y deja aire. */
  --fs-h1: clamp(2.5rem, 5vw, 4rem);       /* 40 → 64 */
  --fs-h2: clamp(1.9rem, 3.4vw, 2.75rem);  /* 30 → 44 */
}

/* ── Hero: altura contenida (que el contenido siguiente asome a 1366×768)
      y eyebrow con el diferenciador ───────────────────────────────────── */
.hero { min-height: auto; padding: 148px 0 80px; }

.hero__eyebrow {
  display: block;
  font-family: var(--font-mono);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--orange);
  margin-bottom: 22px;
}
.hero__content { max-width: 680px; }
.hero__title {
  max-width: none;
  /* Un punto por debajo del h1 global: el titular nuevo es más largo que
     «Despreocúpese de su red» y a 64px rompía en 4 líneas */
  font-size: clamp(2.3rem, 4.4vw, 3.55rem);
}
.hero__sub   { font-size: 1.12rem; max-width: 580px; }

/* ── Nav sólido para páginas internas (el nav base es transparente hasta
      el scroll: sobre cuerpo claro quedaría texto blanco sobre blanco) ── */
.nav--solid {
  background: rgba(17,17,17,.97);
  box-shadow: 0 1px 0 rgba(255,255,255,.07);
}

/* ── Hero compacto de páginas internas ────────────────────────────────── */
.page-hero {
  background: var(--charcoal);
  padding: 148px 0 64px;
  position: relative;
  overflow: hidden;
}
.page-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 55% 70% at 78% 40%, rgba(223,106,46,.08) 0%, transparent 70%);
  pointer-events: none;
}
.crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: .75rem;
  letter-spacing: .04em;
  color: rgba(255,255,255,.5);
  margin-bottom: 20px;
}
.crumbs a { color: rgba(255,255,255,.5); transition: color var(--transition); }
.crumbs a:hover { color: var(--white); }
.page-hero h1 {
  color: var(--white);
  font-size: clamp(2rem, 4vw, 3.2rem);
  margin-bottom: 16px;
  max-width: 20ch;
}
.page-hero__sub {
  color: var(--text-on-dark);
  font-size: 1.1rem;
  max-width: 640px;
}

/* ── Soluciones como lista escaneable (antes: 6 fichas altas) ─────────── */
.sol-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
}
@media (min-width: 760px)  { .sol-list { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .sol-list { grid-template-columns: repeat(3, 1fr); } }

.sol-item {
  display: flex;
  align-items: flex-start;
  gap: 18px;
  padding: 24px 26px;
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-radius: var(--radius);
}
.sol-item__icon { color: var(--orange); flex-shrink: 0; margin-top: 3px; }
.sol-item h3 { font-size: 1.15rem; margin-bottom: 6px; }
.sol-item p  { font-size: .95rem; }
.sol-item__more {
  display: inline-block;
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: .8rem;
  font-weight: 600;
  color: var(--orange-text);
}
.sol-item__more:hover { text-decoration: underline; }

/* ── Índice editorial (teaser de recursos / enlaces a páginas) ────────── */
.link-rows { border-top: 1px solid var(--gray-border); }
.link-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
  padding: 20px 6px;
  border-bottom: 1px solid var(--gray-border);
  color: var(--text-dark);
  font-weight: 600;
  font-size: 1.05rem;
  transition: color var(--transition);
}
.link-row:hover { color: var(--orange-text); }
.link-row__cat {
  display: block;
  font-family: var(--font-mono);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 5px;
}
.link-row svg { flex-shrink: 0; }

/* ── Banda de trayectoria en la home (la sección completa vive ahora en
      trayectoria.html) ──────────────────────────────────────────────── */
.trayectoria-band {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin-top: 40px;
  padding: 26px 30px;
  background: var(--charcoal);
  border-radius: var(--radius);
}
.trayectoria-band p { color: var(--text-on-dark); max-width: 56ch; }
.trayectoria-band strong { color: var(--white); }

/* ── Clientes sin grilla vacía: la sección queda en una banda honesta.
      La grilla de slots vuelve cuando haya logotipos autorizados
      (markup comentado en index.html). ─────────────────────────────── */
.clients-section .section-header { margin-bottom: 0; }
.clients-section .clients-note   { margin-top: 16px; }

/* ── Páginas internas: la sección que sigue al page-hero pierde parte del
      padding superior (el hero ya da el aire) ──────────────────────────── */
.page-hero + section { padding-top: var(--section-py-sm); }

/* ── Sectores: tarjetas un punto más compactas en la home corta ───────── */
.sector-card { padding: 34px 32px; }

/* ── Teaser de recursos en la home (los artículos viven en recursos.html) ── */
.recursos-teaser {
  background: var(--gray-bg);
  padding: var(--section-py-sm) 0;
}

/* Clientes ahora es una banda breve entre dos secciones grises:
   se aclara para que no se fundan, y baja a densidad de banda */
.clients-section {
  background: var(--white);
  padding: var(--section-py-sm) 0;
}

/* ── Compresión de la home corta: sin dobles márgenes ni bandas infladas ── */
.sectores-grid { margin-top: 0; }
.brands-section { padding: var(--section-py-sm) 0; }


/* ══════════════════════════════════════════════════════════════════════
   CAPA «GRADO FABRICANTE» · 2026-08-09
   ──────────────────────────────────────────────────────────────────────
   El listón dejó de ser la competencia local: es la liga de los
   fabricantes que Datatell representa (CommScope, Ubiquiti, Extreme,
   Juniper, Arista). Cada regla de esta capa sale de una medición
   concreta de sus sitios — trazabilidad completa en
   _notas/decisiones-grado-fabricante-2026-08-09.md y el concepto en
   _notas/concepto-grado-fabricante-2026-08-08.md.

   Va al final a propósito: gana por orden sin reescribir la base.
   Para revertir: borrar esta capa y restaurar
   _respaldo/*.antes-de-grado-fabricante-2026-08-09.

   INTOCABLES QUE ESTA CAPA NO PISA: el fix de impresión
   (@media screen + beforeprint), el formulario y su endpoint, los
   canonical, el checkbox de 24px y la normalización de logos por
   [data-brand] (transform/scale por marca — aquí solo se retira el
   filtro grayscale, nunca los ajustes de escala).
   ══════════════════════════════════════════════════════════════════════ */

/* ── 1 · TIPOGRAFÍA DISPLAY FINA ──────────────────────────────────────
      CommScope titula en display-1 de 64px peso 300 (medido en su CSS).
      El sector habla grande y en voz baja: el bold gritón es de
      plantilla local. El 700 queda reservado para énfasis puntual.
      Riesgo declarado: por debajo de ~32px renderizados, el peso 300
      pierde tinta en monitores baratos → en móvil los h2 vuelven a 400. */
h1 {
  font-weight: 300;
  letter-spacing: -0.03em;
  font-size: clamp(2.6rem, 5.4vw, 4.5rem);   /* 41 → 72 px */
  line-height: 1.06;
}
h2 {
  font-weight: 300;
  letter-spacing: -0.025em;
  font-size: clamp(1.9rem, 3.5vw, 2.9rem);   /* 30 → 46 px */
  line-height: 1.14;
}
@media (max-width: 640px) {
  h2 { font-weight: 400; }                    /* < 32px renderizados */
}
.section-header { max-width: 720px; margin-bottom: 52px; }
.section-header p { font-size: 1.02rem; }

/* ── 2 · LIENZO BLANCO CONTINUO CON REGLAS DE 1PX ─────────────────────
      Patrón común de los 4 fabricantes medidos: cuerpo blanco continuo,
      secciones separadas por hairlines y aire — nada de bandas grises
      alternadas ni texturas de puntos (eso es Divi/WordPress local). */
.pain-section,
.solutions-section,
.ind-section,
.brands-section,
.recursos-teaser,
.nosotros-section,
.clients-section,
.form-section {
  background: var(--white);
  padding: 96px 0;
  border-top: 1px solid var(--gray-border);
}
.pain-section { border-top: 0; }              /* el hero oscuro ya corta */

/* Fuera las decoraciones del sistema visual 2026-08-06: glows, clusters
   de puntos y barritas naranjas bajo los h2 — el display fino y las
   reglas de 1px no las piden. (Patrón de plantilla local, rechazado.) */
.pain-section::before, .pain-section::after,
.solutions-section::before, .solutions-section::after,
.form-section::before,
.pain-section .section-header h2::after,
.solutions-section .section-header h2::after,
.brands-section .section-header h2::after,
.responsibility-section::after,
.blog-section::after,
.blog-section .section-header h2::after {
  content: none;
}
/* Y la misma limpieza en las secciones de páginas internas */
.blog-section, .responsibility-section {
  background-image: none;
}
@media (max-width: 760px) {
  .pain-section, .solutions-section, .ind-section, .brands-section,
  .recursos-teaser, .nosotros-section, .form-section { padding: 64px 0; }
}

/* ── 3 · HERO OSCURO CON TOPOLOGÍA DE RED ─────────────────────────────
      Juniper: una idea grande arriba + métricas al pie. Ubiquiti: el
      gráfico técnico ES la imagen de producto — nada de anillos
      decorativos ni stock. El radial difuso se retira: el dibujo de
      red aporta la textura. */
.hero {
  min-height: auto;
  padding: 150px 0 0;
  /* Fondo plano: fuera el rayado diagonal del sistema visual 2026-08-06
     y el radial difuso — texturas de plantilla; la topología SVG es la
     única gráfica del hero */
  background: var(--charcoal);
}
.hero::before { background: none; }
.hero__layout {
  grid-template-columns: 1fr;
  gap: 48px;
  align-items: center;
}
@media (min-width: 980px) {
  .hero__layout { grid-template-columns: minmax(0, 1fr) 460px; }
}
.hero__content { max-width: 660px; }
.hero__title {
  font-weight: 300;
  letter-spacing: -0.03em;
  font-size: clamp(2.4rem, 4.8vw, 4rem);      /* titular largo: un paso
                                                  bajo el h1 global */
  line-height: 1.08;
  margin-bottom: 24px;
}
.hero__title::after { display: none; }         /* muere la barrita — el
                                                  display fino no la pide */
.hero__sub { font-size: 1.1rem; max-width: 560px; margin-bottom: 18px; }
.hero__tagline { margin-bottom: 32px; font-style: normal; }
.hero__ctas { align-items: center; gap: 26px; margin-bottom: 18px; }

.hero__viz { display: none; }
@media (min-width: 980px) {
  .hero__viz { display: block; }
  .hero__topology { width: 100%; height: auto; }
}

/* Cifras monoespaciadas al pie del hero (Juniper + rechazo del contador
   JS animado de la competencia: cifras quietas, tipografía de dato) */
.hero__metrics {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px 32px;
  border-top: 1px solid rgba(255,255,255,.14);
  margin-top: 56px;
  padding: 28px 0 36px;
}
@media (min-width: 760px) {
  .hero__metrics { grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); }
}
.hero__metric { display: flex; flex-direction: column; gap: 4px; }
.hero__metric-value {
  font-family: var(--font-mono);
  font-size: 1.55rem;
  font-weight: 500;
  color: var(--white);
  line-height: 1;
}
.hero__metric-label {
  font-size: .8rem;
  color: rgba(255,255,255,.48);
  letter-spacing: .02em;
}

/* ── 4 · CTAS RECTANGULARES + ENLACES CON FLECHA ──────────────────────
      Ubiquiti/Arista: rectángulo de radio mínimo, borde de 1px, peso
      500. Mueren los botones píldora con sombra (FONT, Vinet, el sitio
      anterior). El secundario deja de ser botón: es enlace con flecha. */
.btn {
  border-radius: 2px;
  font-weight: 500;
  letter-spacing: .01em;
}
.btn--primary { border-width: 1px; }
.btn--primary:hover { box-shadow: none; }
.btn--outline { border-width: 1px; }
.btn--nav { border-radius: 2px; border-width: 1px; }
.btn--soporte { border-radius: 2px; border-width: 1px; font-weight: 600; }
.btn--white { border-width: 1px; font-weight: 600; }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: .86rem;
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--orange-text);
  transition: color var(--transition);
}
.link-arrow svg { transition: transform var(--transition); flex-shrink: 0; }
.link-arrow:hover svg { transform: translateX(4px); }
.link-arrow--light { color: var(--white); }
.link-arrow--light:hover { color: var(--orange-light); }

/* CTA contextual: de tarjeta gris flotante a fila con regla — el lienzo
   no se interrumpe con cajitas */
.ctx-cta, .ctx-cta--white {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--gray-border);
  border-radius: 0;
  padding: 22px 0 0;
  margin-top: 44px;
}
.ctx-cta:hover { border-color: var(--gray-border); }
.ctx-cta__link {
  font-family: var(--font-mono);
  font-size: .86rem;
  color: var(--orange-text);
}

/* ── 5 · PROBLEMA: COLUMNAS CON REGLA, SIN TARJETAS DE ICONITO ────────
      La tarjeta con icono redondeado es la firma de la plantilla WP
      universal — rechazada. Tres columnas de texto con hairline. */
.gf-cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: 36px;
}
@media (min-width: 860px) { .gf-cols { grid-template-columns: repeat(3, 1fr); gap: 44px; } }
.gf-col { border-top: 1px solid var(--gray-border); padding-top: 24px; }
.gf-col h3 { font-size: 1.08rem; font-weight: 600; margin-bottom: 10px; letter-spacing: -0.01em; }
.gf-col p { font-size: .95rem; color: var(--text-muted); }

/* ── 6 · SOLUCIONES COMO FAMILIAS NUMERADAS 01–06 ─────────────────────
      Ubiquiti spec-sheet / tablas de producto CommScope: filas con
      regla superior, número monoespaciado y chips de especificación.
      Hoja de datos, no tarjetas. */
.spec-list { border-top: 1px solid var(--charcoal); }
.spec-row {
  display: grid;
  grid-template-columns: 52px 1fr;
  gap: 6px 20px;
  padding: 28px 0;
  border-bottom: 1px solid var(--gray-border);
  transition: background var(--transition);
}
@media (min-width: 960px) {
  .spec-row {
    /* Cuarta pista desde el 2026-08-26: la miniatura. Se le da medida
       fija (168px) y no una fracción, porque una foto que cambia de
       tamaño con la ventana rompe la columna de la izquierda —los nueve
       bloques de texto dejarían de arrancar en la misma vertical y la
       lista se leería como nueve tarjetas sueltas en vez de un índice. */
    grid-template-columns: 72px 168px minmax(0, 1.3fr) minmax(0, 1fr);
    gap: 24px;
    padding: 28px 0;
  }
}
.spec-row__num {
  font-family: var(--font-mono);
  font-size: .84rem;
  font-weight: 500;
  color: var(--gray-light);
  padding-top: 7px;
}
.spec-row__body h3 {
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin-bottom: 6px;
}
.spec-row__body p { font-size: .95rem; max-width: 56ch; }
.spec-row__body .link-arrow { margin-top: 10px; }
.spec-row__chips {
  grid-column: 2;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 8px;
  margin-top: 6px;
}
@media (min-width: 960px) {
  .spec-row__chips {
    grid-column: auto;
    justify-content: flex-end;
    margin-top: 7px;
  }
}
/* ── Chips con definición (2026-08-10) ────────────────────────────────
      Antes: <li> con borde gris lavado que no decía nada a quien no
      conoce el término. Ahora: <details> nativo — el chip resalta
      (borde definido, mono con peso, «+» naranja) y al tocarlo se abre
      una línea en lenguaje llano: qué es y qué problema resuelve. */
.spec-row__chips li { min-width: 0; }
.spec-row__chips li:has(.chip-def[open]) { flex-basis: 100%; }
.chip-def summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .03em;
  color: var(--charcoal);
  background: var(--white);
  border: 1px solid rgba(17,17,17,.42);
  border-radius: 2px;
  padding: 5px 11px;
  white-space: nowrap;
  transition: border-color var(--transition), background var(--transition), color var(--transition);
}
.chip-def summary::-webkit-details-marker { display: none; }
.chip-def summary::after {
  content: "+";
  color: var(--orange);
  font-weight: 600;
  line-height: 1;
}
.chip-def summary:hover,
.chip-def summary:focus-visible { border-color: var(--orange); }
.chip-def[open] summary {
  background: var(--charcoal);
  color: var(--white);
  border-color: var(--charcoal);
}
.chip-def[open] summary::after { content: "−"; }
.chip-def__panel {
  margin-top: 8px;
  padding: 12px 14px;
  max-width: 56ch;
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-left: 2px solid var(--orange);
  border-radius: 2px;
}
.chip-def__panel p {
  font-family: var(--font);
  font-size: .84rem;
  line-height: 1.6;
  letter-spacing: 0;
  color: var(--text-body);
  white-space: normal;
}
.chip-def__panel strong {
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .03em;
  color: var(--charcoal);
}
.chip-def__panel .link-arrow {
  margin-top: 8px;
  font-size: .8rem;
  white-space: normal;
}
@media (min-width: 960px) {
  /* La columna de chips va alineada a la derecha; el panel abierto
     también, para que la fila conserve su composición. */
  .spec-row__chips li:has(.chip-def[open]) { text-align: right; }
  .chip-def__panel { display: inline-block; text-align: left; }
}
.spec-row:hover { background: #FAFAFA; }

/* ── 7 · INDUSTRIAS EN COLUMNAS DE VERTICALES ─────────────────────────
      Extreme Networks organiza su home por verticales («K-12
      Education», «State & Local Government») como categorías de primer
      nivel. Misma arquitectura: listas escaneables, no dos supercajas. */
.ind-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 56px;
}
@media (min-width: 860px) { .ind-grid { grid-template-columns: 1fr 1fr; gap: 72px; } }
.ind-group__label {
  font-family: var(--font-mono);
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--orange-text);
  margin-bottom: 14px;
}
.ind-list { border-top: 1px solid var(--charcoal); }
.ind-list li {
  padding: 15px 0 14px;
  border-bottom: 1px solid var(--gray-border);
}
.ind-list strong {
  display: block;
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--text-dark);
  letter-spacing: -0.01em;
}
.ind-list span { font-size: .88rem; color: var(--text-muted); }
.ind-note {
  margin-top: 18px;
  font-size: .88rem;
  color: var(--text-muted);
  max-width: 52ch;
}

/* ── 8 · MURO DE LOGOS EN CELDAS DE BORDE FINO ────────────────────────
      Partner-wall de fabricante: celdas separadas por una retícula real
      de 1px (la grilla aporta el fondo-línea), sobre blanco, y los
      logos SIN filtro que los lave. La normalización por [data-brand]
      (escalas por marca) NO se toca. */
.brands-grid {
  gap: 1px;
  background: var(--gray-border);
  border: 1px solid var(--gray-border);
}
.brand-item,
.brand-item--static {
  background: var(--white);
  border: 0;
  border-radius: 0;
  box-shadow: none;
  min-height: 108px;
}
.brand-item:hover {
  box-shadow: none;
  transform: none;
  background: #FAFAFA;
}
.brand-item img {
  filter: none;
  opacity: 1;
}

/* Clientes, fundido como nota al pie del muro (antes: sección entera
   para un párrafo) */
/* 2026-08-26 · Se agranda y se le quita la regla de arriba.
   El bloque presenta el muro de clientes —la prueba más fuerte que
   tiene la portada— y estaba compuesto como un pie de página: título
   de 1,06rem y párrafo de 0,92, más chicos que el cuerpo normal del
   sitio. La línea de 1px encima lo remataba: separaba el texto del
   muro que introduce, cuando lo que hace falta es que se lean como
   una sola cosa. */
.clients-inline {
  margin-top: 56px;
  padding-top: 0;
  max-width: 820px;
}
.clients-inline__title {
  font-size: 1.6rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin-bottom: 12px;
}
.clients-inline p { font-size: 1.06rem; line-height: 1.7; color: var(--text-muted); }
@media (min-width: 1700px) {
  .clients-inline__title { font-size: 1.75rem; }
}

/* ── 9 · NOSOTROS: DATOS COMO FICHA, BANDA → FILA ─────────────────────
      Las cifras en monoespaciada (dato, no marketing); la banda oscura
      de trayectoria pasa a fila con regla — el lienzo sigue blanco. */
.nosotros-fact {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--gray-border);
  border-radius: 0;
  box-shadow: none;
  padding: 16px 0 4px;
}
.nosotros-fact__value {
  font-family: var(--font-mono);
  font-size: 1.35rem;
  font-weight: 500;
  color: var(--text-dark);
}
.trayectoria-band {
  background: transparent;
  border-radius: 0;
  border-top: 1px solid var(--gray-border);
  padding: 24px 0 0;
  margin-top: 48px;
}
.trayectoria-band p { color: var(--text-body); }
.trayectoria-band strong { color: var(--text-dark); }

/* ── 10 · CONTACTO COMO PANEL DIVIDIDO ────────────────────────────────
      Columna oscura con los canales + formulario en tarjeta blanca con
      regla superior naranja. El formulario y su endpoint NO se tocan:
      solo el contenedor. */
.form-layout { align-items: stretch; }
.form-intro {
  background: var(--charcoal);
  padding: 44px 40px;
}
@media (max-width: 640px) { .form-intro { padding: 32px 24px; } }
.form-intro h2 { color: var(--white); }
.form-intro > p { color: rgba(255,255,255,.65); }
.form-intro .contact-list li { color: rgba(255,255,255,.65); }
.form-intro .contact-list a { color: var(--white); }
.form-intro .contact-list a:hover { color: var(--orange-light); }
.form-intro .whatsapp-link { border-radius: 2px; }
.form-intro .social-follow { border-top-color: rgba(255,255,255,.14); }
.form-intro .social-follow__title { color: rgba(255,255,255,.5); }
.form-intro .social-follow__text { color: rgba(255,255,255,.55); }
.form-intro .soc-btn {
  background: transparent;
  border: 1px solid rgba(255,255,255,.25);
  color: var(--white);
  border-radius: 2px;
}
.form-intro .soc-btn:hover { background: rgba(255,255,255,.08); transform: none; }
.form-intro .soc-btn--linkedin { background: transparent; border-color: rgba(255,255,255,.25); }
.form-intro .soc-btn--linkedin:hover { background: rgba(255,255,255,.08); }

.contact-form {
  border-radius: 2px;
  border-top: 3px solid var(--orange);
  box-shadow: none;
}

/* ── 11 · STICKY CTA RECOMPUESTO ──────────────────────────────────────
      Mismo comportamiento (aparece tras el hero, se oculta en
      #contacto), forma de fabricante: rectángulo, sin salto al hover. */
.sticky-cta__main {
  border-radius: 2px;
  box-shadow: 0 2px 14px rgba(0,0,0,.25);
}
.sticky-cta__main:hover { transform: none; }
.sticky-cta__wa { border-radius: 2px; }
.sticky-cta__wa:hover { transform: none; }

/* ── 12 · HERENCIA EN PÁGINAS INTERNAS ────────────────────────────────
      Nav, tipos, botones y footer comparten clases: las internas toman
      el sistema sin reescribir sus HTML. */
.page-hero h1 {
  font-weight: 300;
  letter-spacing: -0.03em;
  font-size: clamp(2.3rem, 4.4vw, 3.6rem);
  max-width: 24ch;
}
.page-hero::before { background: none; }
.link-row { font-weight: 500; padding: 22px 4px; }
.link-row:first-child { border-top: 0; }
.link-rows { border-top: 1px solid var(--charcoal); }

/* El eyebrow ya era mono + naranja (se conserva de la base): activo
   raro y muy «infraestructura», igual que IBM Plex Mono. */

/* ── 13 · FOTOS PROPIAS (2026-08-10) ──────────────────────────────────
      Fotos reales del equipo desde el Drive de material RAW. Mismo radio
      y contención que las tarjetas; nada de filtros: la foto real es el
      activo, no se estiliza. */
.nosotros-photo,
.page-photo {
  margin: 40px auto 0;
  max-width: 860px;
}
.nosotros-photo img,
.page-photo img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
}
.page-photo { margin-bottom: 48px; }

/* ── 14 · MURO DE CLIENTES (2026-08-10, a color desde el mismo día) ───
      Decisión de Julián: el muro de clientes es prueba, no lista de
      marcas — el color institucional (CCSS, ICE, TSE…) se reconoce al
      instante y en gris se perdía. A diferencia del muro de
      fabricantes, acá NO hay filtro de grises: el orden lo pone la
      retícula (celdas iguales, borde fino) y la igualación de tamaño
      percibido por tipo de logo, no la paleta.
      Pesos ópticos: los sellos compactos y las cajas de color saturado
      pesan más por cm² que los lockups lineales — se compensa con
      cuatro alturas máximas (seal 52 / boxy 44 / lineal 40 / wide 26),
      el mismo criterio de las compensaciones de Microchip/Airspan/
      Netcom en el muro de fabricantes. */
.client-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px 16px;
  min-height: 96px;
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-radius: var(--radius);
}
.client-cell img {
  max-height: 40px;          /* lockups lineales (BCCR, TSE, MEIC, CNFL, UNA) */
  width: auto;
  /* 2026-08-28 · El tope era `156px` a secas y desbordaba en celular.
     En una pantalla de 390px cada celda queda con unos 124px de espacio
     útil después del padding, pero la imagen tenía permiso hasta 156: se
     salía de la tarjeta unos treinta píxeles y los logos anchos —ICE,
     MEIC, AstraZeneca— aparecían cortados contra el borde.
     `min()` conserva el tope de 156 en pantallas donde la celda da para
     eso, y en las angostas manda el 100% de la celda. */
  max-width: min(156px, 100%);
  object-fit: contain;
  transition: transform 250ms var(--ease);
}
.client-cell:hover img { transform: scale(1.04); }
/* Sellos y escudos compactos: más alto de fila para igualar el área
   percibida (CCSS, Desamparados, y el escudo del PJ). */
.client-cell img.client-logo--seal { max-height: 52px; }
/* Marcas en caja/isotipo denso (ICE, RACSA): punto intermedio. */
.client-cell img.client-logo--boxy { max-height: 44px; }
/* Lockups muy horizontales (CNM): todo el ancho de la celda, poca
   altura, para que el texto siga legible. */
.client-cell img.client-logo--wide {
  max-width: 100%;
  max-height: 26px;
}
/* Poder Judicial: su sitio solo publica la marca en blanco (monocromo
   oficial). Se invierte por CSS para que exista sobre lienzo claro —
   presentación, no edición del archivo — y queda anotado que no hay
   versión a color que restituir. */
.client-cell img.client-logo--invert {
  filter: invert(1) brightness(0.35);
}
/* La grilla hereda .clients-grid (definida arriba); espacio respecto al
   texto introductorio del bloque de clientes. */
.clients-inline + .clients-grid { margin-top: 28px; }

/* ── 15 · AUTORÍA EN RECURSOS (2026-08-10) ────────────────────────────
      Firma sobria de autor en tarjeta y modal — sin cargo, biografía ni
      foto. El marcado estructurado (Article/author) vive en el head de
      recursos.html. */
.blog-card__author,
.rec-modal__author {
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .03em;
  color: var(--text-muted);
  margin: 6px 0 0;
}
.rec-modal__author { margin: -6px 0 14px; }

/* Con 13 celdas, la última quedaba sola a la izquierda en la retícula
   de 4: se centra, igual que en el muro de fabricantes. */
@media (min-width: 860px) {
  .clients-grid > .client-cell:last-child:nth-child(4n + 1) {
    grid-column: 2 / 4;
    justify-self: center;
    width: calc(50% - 10px);
  }
}

/* ── 16 · ARTÍCULOS DESARROLLADOS EN RECURSOS (2026-08-10) ────────────
      Los modales pasaron de lista suelta a artículo: párrafos de
      introducción y desarrollo alrededor de la lista. */
.rec-modal__body p {
  margin: 0 0 14px;
  font-size: .98rem;
  line-height: 1.65;
}
.rec-modal__body + .rec-modal__list { margin-top: 4px; }

/* ── 17 · CASOS DE ÉXITO (2026-08-10) ─────────────────────────────────
      INERTE A PROPÓSITO: hoy ninguna clase de este bloque aparece en el
      HTML publicado. El markup está escrito y comentado en index.html,
      justo debajo del muro de clientes, esperando el contenido real de
      Julián. Se deja el CSS listo para que publicar sea quitar los dos
      delimitadores del comentario y nada más — sin volver a inventar
      estilos a las carreras el día que llegue el texto.
      Sistema: grado fabricante (lienzo blanco, hairlines, mono para las
      etiquetas, naranja como único acento). Sin sombras ni píldoras. */
.cases {
  margin-top: 96px;
  padding-top: 48px;
  border-top: 1px solid var(--gray-border);
}
.cases__title {
  font-size: clamp(1.5rem, 3vw, 2rem);
  font-weight: 300;
  letter-spacing: -.02em;
  margin: 0 0 10px;
}
.cases__intro {
  max-width: 60ch;
  color: var(--text-muted);
  margin: 0 0 40px;
}
.cases__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1px;
  background: var(--gray-border);
  border: 1px solid var(--gray-border);
}
.case-card {
  background: #fff;
  padding: 28px 26px 30px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.case-card__sector {
  font-family: var(--font-mono, 'IBM Plex Mono', monospace);
  font-size: .7rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--orange);
  margin: 0;
}
.case-card__challenge {
  font-size: 1.12rem;
  font-weight: 400;
  line-height: 1.35;
  margin: 0;
}
.case-card__work,
.case-card__result {
  font-size: .93rem;
  line-height: 1.6;
  color: var(--text-muted);
  margin: 0;
}
.case-card__work span,
.case-card__result span {
  display: block;
  font-family: var(--font-mono, 'IBM Plex Mono', monospace);
  font-size: .68rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gray-light, #999);
  margin-bottom: 4px;
}
.case-card__result {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--gray-border);
  color: var(--charcoal);
}
.case-note {
  margin: 22px 0 0;
  font-size: .8rem;
  line-height: 1.55;
  color: var(--gray-light, #999);
  max-width: 72ch;
}

/* ── 17b · ENLACE DE LA TARJETA DE CASO (2026-08-24) ───────────────────
      El bloque 17 se escribió el 10 de agosto para tarjetas SIN enlace:
      en ese momento los casos no existían como artículo. Ya existen —los
      tres de Rachel, en recursos/— así que cada tarjeta ahora lleva a su
      caso completo. Esto es lo único que se agrega al sistema del 17; no
      se tocó ninguna regla anterior.
      El título es el destino clicable, y el "Leer el caso" de abajo es
      decorativo (aria-hidden) para no duplicar el enlace ante un lector
      de pantalla — mismo patrón que .blog-card. */
.case-card__challenge a {
  color: inherit;
  text-decoration: none;
  background-image: linear-gradient(var(--orange), var(--orange));
  background-size: 0 1px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  transition: background-size var(--transition, 200ms ease);
}
.case-card__challenge a:hover,
.case-card__challenge a:focus-visible {
  background-size: 100% 1px;
}
.case-card__link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: .82rem;
  font-weight: 500;
  color: var(--orange);
  margin-top: 2px;
}
.case-card:hover .case-card__link svg {
  transform: translateX(3px);
}
.case-card__link svg {
  transition: transform var(--transition, 200ms ease);
}
@media (max-width: 640px) {
  .cases { margin-top: 64px; padding-top: 36px; }
  .case-card { padding: 24px 20px 26px; }
}

/* ── 18 · DIAGRAMA INTERACTIVO IA PRIVADA ─────────────────────────────
   Topología de flujo: documentos → servidor on-premise → respuesta.
   Toggle de comparación con nube pública. Sin JS externo. */
.ia-viz {
  background: var(--charcoal);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 2px;
  margin: 48px 0 56px;
  overflow: hidden;
}
.ia-viz__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 20px;
  background: rgba(255,255,255,.04);
  border-bottom: 1px solid rgba(255,255,255,.08);
  gap: 16px;
  flex-wrap: wrap;
}
.ia-viz__label {
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: var(--ls-eyebrow);
  color: rgba(255,255,255,.35);
}
.ia-viz__toggle {
  font-family: var(--font-mono);
  font-size: .72rem;
  color: var(--orange);
  background: none;
  border: 1px solid rgba(223,106,46,.35);
  border-radius: 2px;
  padding: 5px 14px;
  cursor: pointer;
  transition: background 180ms, border-color 180ms;
  white-space: nowrap;
}
.ia-viz__toggle:hover,
.ia-viz__toggle[aria-pressed="true"] {
  background: rgba(223,106,46,.1);
  border-color: rgba(223,106,46,.6);
}

.ia-viz__stage {
  padding: 36px 24px 28px;
}
.ia-viz__boundary {
  border: 1px dashed rgba(255,255,255,.18);
  border-radius: 3px;
  padding: 36px 24px 28px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ia-viz__boundary-label {
  position: absolute;
  top: -9px;
  left: 16px;
  background: var(--charcoal);
  padding: 0 8px;
  font-family: var(--font-mono);
  font-size: .62rem;
  letter-spacing: .14em;
  color: rgba(255,255,255,.28);
}
.ia-viz__row {
  display: flex;
  align-items: center;
  gap: 0;
  width: 100%;
  max-width: 680px;
}
.ia-viz__node {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  min-width: 100px;
  flex-shrink: 0;
}
.ia-viz__icon {
  width: 60px;
  height: 60px;
  border-radius: 4px;
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.12);
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255,255,255,.55);
}
.ia-viz__icon--server {
  border-color: rgba(223,106,46,.4);
  background: rgba(223,106,46,.06);
  color: var(--orange);
}
.ia-viz__icon--response {
  color: rgba(255,255,255,.55);
}
.ia-viz__icon--cloud {
  border-color: rgba(220,38,38,.35);
  background: rgba(220,38,38,.06);
  color: rgba(220,38,38,.7);
}
.ia-viz__node-name {
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .04em;
  color: rgba(255,255,255,.65);
  text-align: center;
  line-height: 1.3;
}
.ia-viz__node-sub {
  font-size: .6rem;
  color: rgba(255,255,255,.28);
  text-align: center;
  line-height: 1.3;
  font-family: var(--font-mono);
}
.ia-viz__node-sub--danger { color: rgba(220,38,38,.65); }

.ia-viz__pipe {
  flex: 1;
  height: 2px;
  background: rgba(255,255,255,.1);
  position: relative;
  overflow: hidden;
  margin: 0 4px;
  align-self: center;
  margin-bottom: 20px;
}
.ia-viz__pipe--danger {
  background: rgba(220,38,38,.2);
}
.ia-viz__dot {
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--orange);
  top: -2.5px;
  animation: ia-flow 1.6s linear infinite;
}
.ia-viz__dot--danger {
  background: #dc2626;
}
.ia-viz__dot:nth-child(2) { animation-delay: .53s; }
.ia-viz__dot:nth-child(3) { animation-delay: 1.06s; }
@keyframes ia-flow {
  0%   { left: -8px; opacity: 0; }
  8%   { opacity: 1; }
  92%  { opacity: 1; }
  100% { left: calc(100% + 8px); opacity: 0; }
}

.ia-viz__outside {
  display: flex;
  align-items: center;
  padding: 28px 24px 0;
  gap: 16px;
}
.ia-viz__barrier {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
.ia-viz__barrier-line {
  width: 2px;
  height: 60px;
  background: repeating-linear-gradient(
    to bottom,
    rgba(220,38,38,.5) 0, rgba(220,38,38,.5) 6px,
    transparent 6px, transparent 10px
  );
}
.ia-viz__barrier-text {
  font-family: var(--font-mono);
  font-size: .58rem;
  letter-spacing: .08em;
  color: rgba(220,38,38,.55);
  text-align: center;
  writing-mode: horizontal-tb;
  padding: 3px 6px;
  border: 1px solid rgba(220,38,38,.25);
  border-radius: 1px;
  white-space: nowrap;
}
.ia-viz__node--cloud .ia-viz__icon {
  border-color: rgba(220,38,38,.35);
  background: rgba(220,38,38,.06);
  color: rgba(220,38,38,.7);
}

.ia-viz__caption {
  font-size: .78rem;
  color: rgba(255,255,255,.28);
  text-align: center;
  font-family: var(--font-mono);
  letter-spacing: .02em;
  padding: 0 24px 24px;
  border-top: 1px solid rgba(255,255,255,.05);
  padding-top: 16px;
}

@media (max-width: 600px) {
  .ia-viz__row { flex-wrap: wrap; justify-content: center; gap: 20px; }
  .ia-viz__pipe { display: none; }
  .ia-viz__node { min-width: 80px; }
}

/* ════════════════════════════════════════════════════════════
   PÁGINA LEGAL (privacidad.html)
   ════════════════════════════════════════════════════════════
   Bloque de prosa larga, pensado para lectura seguida — un
   funcionario de proveeduría la lee de arriba abajo. Columna
   angosta (68ch) para que la línea no se vuelva ilegible, y
   jerarquía visual mínima: no hay tarjetas ni adornos.
   No introduce variables ni fuentes nuevas. */
.legal-section {
  padding: var(--section-py) 0;
  background: var(--white);
}
.legal {
  max-width: 68ch;
}
.legal__updated {
  font-family: var(--font-mono);
  font-size: .78rem;
  letter-spacing: .02em;
  color: var(--text-muted);
  padding-bottom: 20px;
  margin-bottom: 28px;
  border-bottom: 1px solid var(--gray-border);
}
.legal__lead {
  font-size: 1.08rem;
  color: var(--text-body);
  margin-bottom: 8px;
}
.legal h2 {
  font-size: 1.3rem;
  letter-spacing: var(--ls-tight);
  margin-top: 44px;
  margin-bottom: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--gray-border);
}
.legal p {
  color: var(--text-body);
  margin-bottom: 14px;
}
.legal ul {
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
}
.legal ul li {
  position: relative;
  padding-left: 20px;
  margin-bottom: 10px;
  color: var(--text-body);
}
.legal ul li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: .62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--orange);
}
/* Bloques de datos (responsable, contacto): sin viñeta, tabulados */
.legal ul.legal__data li { padding-left: 0; }
.legal ul.legal__data li::before { display: none; }
.legal ul.legal__rights li { margin-bottom: 12px; }

/* ════════════════════════════════════════════════════════════
   PÁGINA 404 (404.html)
   ════════════════════════════════════════════════════════════
   Importa durante la migración: quien llega acá venía buscando algo
   concreto del sitio viejo. La página no se disculpa, ofrece salidas.
   No introduce variables ni fuentes nuevas. */
.err__code {
  font-family: var(--font-mono);
  font-size: clamp(3.4rem, 9vw, 5.5rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: var(--ls-tight);
  color: var(--orange);
  opacity: .9;
  margin-bottom: 10px;
}
.err-section {
  padding: var(--section-py) 0;
  background: var(--white);
}
.err-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 44px;
  align-items: start;
}
@media (min-width: 900px) {
  .err-grid { grid-template-columns: 1.25fr 1fr; gap: 64px; }
}
.err-col h2 {
  font-size: 1.35rem;
  letter-spacing: var(--ls-tight);
  margin-bottom: 20px;
}
.err-links {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--gray-border);
}
.err-links li {
  padding: 16px 4px;
  border-bottom: 1px solid var(--gray-border);
}
.err-links li a {
  display: block;
  font-weight: 600;
  color: var(--text-dark);
  margin-bottom: 3px;
  transition: color var(--transition);
}
.err-links li a:hover { color: var(--orange); }
.err-links li span {
  display: block;
  font-size: .9rem;
  color: var(--text-muted);
}
.err-box {
  background: var(--gray-bg);
  border: 1px solid var(--gray-border);
  border-radius: var(--radius);
  padding: 26px 24px;
  margin-bottom: 20px;
}
.err-box--plain { background: var(--white); }
.err-box h3 {
  font-size: 1.05rem;
  margin-bottom: 10px;
}
.err-box p {
  font-size: .93rem;
  color: var(--text-body);
  margin-bottom: 12px;
}
.err-box__list {
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
}
.err-box__list li {
  position: relative;
  padding-left: 18px;
  margin-bottom: 9px;
  font-size: .9rem;
  color: var(--text-body);
}
.err-box__list li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: .6em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--orange);
}
.err-box__contact {
  list-style: none;
  margin: 0;
  padding: 0;
}
.err-box__contact li {
  font-size: .92rem;
  color: var(--text-muted);
  margin-bottom: 9px;
}
.err-box__contact a {
  color: var(--orange-text, var(--orange));
  font-weight: 600;
}
.err-box__contact a:hover { text-decoration: underline; }


/* ═══════════════════════════════════════════════════════════════════════
   TANDA 2026-08-19 — HERO ROTATIVO · MENÚ SOLUCIONES · LOGO
   ═══════════════════════════════════════════════════════════════════════
   Este bloque va al final a propósito: la hoja está construida por capas
   fechadas y la última gana. No usa ni un color ni una tipografía que no
   estuviera ya en :root — naranja de marca, charcoal, IBM Plex.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Utilidad: solo para lector de pantalla ─────────────────────────────
      No existía en la hoja. La necesita el anuncio de cambio de pantalla
      del carrusel. `clip-path` moderno, sin el hack de clip: rect(). */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ═══ 1 · HERO ROTATIVO ═════════════════════════════════════════════════

   Las cuatro pantallas se apilan en la MISMA celda de un grid 1×1. Esto
   resuelve dos cosas de un golpe:

   · El contenedor toma la altura de la pantalla más alta, así que al rotar
     nada salta ni empuja lo que viene abajo (posicionar en absoluto habría
     colapsado la altura y obligado a fijarla a mano).
   · Cada pantalla mantiene su propio `.hero__layout`, o sea el grid de dos
     columnas ya existente, sin duplicar reglas.

   Las inactivas usan `visibility: hidden`, no solo `opacity: 0`: eso las
   saca del orden de tabulación. Un carrusel donde el Tab cae en botones
   invisibles es un carrusel roto para quien navega con teclado. */

.hero__carousel { position: relative; }

.hero__slides {
  display: grid;
  grid-template-columns: 1fr;
}
.hero__slide {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity .55s var(--ease),
              transform .55s var(--ease),
              visibility 0s linear .55s;
}
.hero__slide.is-active {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity .55s var(--ease),
              transform .55s var(--ease),
              visibility 0s;
}

/* Los titulares 2 a 4 son <p>, no <h1>: la página conserva un solo H1
   («Despreocúpese de su red»). Aquí solo se replica el aspecto. */
.hero__title--slide {
  font-weight: 300;
  letter-spacing: -0.03em;
  font-size: clamp(2.4rem, 4.8vw, 4rem);
  line-height: 1.08;
  margin-bottom: 24px;
  color: var(--white);
  max-width: none;
}

/* ── Controles ─────────────────────────────────────────────────────────
      Fila baja, discreta, alineada con el texto. Nada de flechas grandes
      superpuestas al contenido. */
.hero__controls {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-top: 34px;
  flex-wrap: wrap;
}
.hero__dots {
  display: flex;
  align-items: center;
  gap: 10px;
}
.hero__dot {
  position: relative;
  width: 34px;
  height: 22px;              /* área táctil real, la barra visible es fina */
  padding: 0;
  background: none;
  border: none;
  display: flex;
  align-items: center;
  cursor: pointer;
}
.hero__dot::before {
  content: '';
  display: block;
  width: 100%;
  height: 2px;
  background: rgba(255,255,255,.22);
  transition: background var(--transition);
}
.hero__dot:hover::before { background: rgba(255,255,255,.45); }
.hero__dot.is-active::before { background: rgba(255,255,255,.22); }

/* La barrita de progreso vive dentro del punto activo: dice cuánto falta
   sin agregar un elemento nuevo a la interfaz. */
.hero__dot-fill {
  position: absolute;
  left: 0;
  height: 2px;
  width: 0;
  background: var(--orange);
}
.hero__dot.is-active .hero__dot-fill { width: 100%; }
.hero__carousel.is-playing .hero__dot.is-active .hero__dot-fill {
  animation: heroDotFill var(--hero-interval, 7000ms) linear forwards;
}
@keyframes heroDotFill { from { width: 0; } to { width: 100%; } }

.hero__dot:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 4px;
}

.hero__pause {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px;
  border: 1px solid rgba(255,255,255,.16);
  border-radius: 2px;
  background: none;
  color: rgba(255,255,255,.55);
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color var(--transition), border-color var(--transition);
}
.hero__pause:hover {
  color: var(--white);
  border-color: rgba(255,255,255,.4);
}
.hero__pause:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
}
.hero__pause-icon--play  { display: none; }
.hero__pause[aria-pressed="true"] .hero__pause-icon--pause { display: none; }
.hero__pause[aria-pressed="true"] .hero__pause-icon--play  { display: inline; }

/* En móvil el hero ya es alto; los controles se aprietan un poco. */
@media (max-width: 760px) {
  .hero__controls { margin-top: 26px; gap: 14px; }
  .hero__dot { width: 28px; }
}

/* Deslizable en móvil: el JS lee touchstart/touchend, pero hay que evitar
   que el navegador interprete el gesto horizontal como scroll de página. */
@media (max-width: 979px) {
  .hero__slides { touch-action: pan-y; }
}

/* ── prefers-reduced-motion — NO NEGOCIABLE ────────────────────────────
      Si el sistema pide menos movimiento: no hay rotación automática (eso
      lo corta el JS antes de arrancar el temporizador), no hay
      desplazamiento y no hay barrita animada. Los puntos siguen siendo
      clicables: el usuario cambia de pantalla si quiere, cuando quiere.
      El cambio manual conserva un fundido muy corto para no dar un salto
      seco, que es lo que la preferencia busca evitar. */
@media (prefers-reduced-motion: reduce) {
  .hero__slide,
  .hero__slide.is-active {
    transform: none;
    transition: opacity .01ms linear, visibility 0s;
  }
  .hero__carousel.is-playing .hero__dot.is-active .hero__dot-fill {
    animation: none;
    width: 100%;
  }
}

/* ═══ 2 · MENÚ «SOLUCIONES» ═════════════════════════════════════════════

   Escritorio (≥1200px): panel flotante bajo el botón, abre con hover o con
   clic/Enter. Por debajo (<1200px): lista estática dentro del menú
   hamburguesa —un panel flotante dentro de un panel no funciona con el
   pulgar—, solo por clic. El corte es 1200 y no 860 por lo explicado en
   el bloque 3: es el ancho a partir del cual el menú completo cabe. */

.nav__dd { position: relative; }

.nav__dd-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  /* hereda tamaño, peso y color de .nav__link */
}
.nav__dd-btn:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 4px;
}
.nav__dd-caret { transition: transform var(--transition); }
.nav__dd-btn[aria-expanded="true"] { color: var(--white); }
.nav__dd-btn[aria-expanded="true"] .nav__dd-caret { transform: rotate(180deg); }

.nav__dd-menu {
  list-style: none;
  margin: 0;
  padding: 0;
  display: none;
}
.nav__dd.is-open > .nav__dd-menu { display: block; }

.nav__dd-link {
  display: flex;
  align-items: baseline;
  gap: 12px;
  color: rgba(255,255,255,.78);
  font-size: .9rem;
  font-weight: 500;
  line-height: 1.3;
  transition: color var(--transition), background var(--transition);
}
.nav__dd-link:hover,
.nav__dd-link:focus-visible { color: var(--white); }
.nav__dd-link:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: -2px;
}
.nav__dd-num {
  font-family: var(--font-mono);
  font-size: .7rem;
  color: var(--orange);
  letter-spacing: .06em;
  flex: none;
}
.nav__dd-link--all { color: var(--orange); font-weight: 600; }

/* ── Escritorio: panel flotante ── */
@media (min-width: 1200px) {
  .nav__dd-menu {
    position: absolute;
    top: calc(100% + 14px);
    left: -18px;
    min-width: 306px;
    /* Opaco, no rgba: el panel se abre sobre secciones de fondo claro y
       cualquier transparencia deja leer el texto de abajo a través de los
       enlaces. Se vio en la captura de verificación del 2026-08-19. */
    background: var(--charcoal-mid);
    border: 1px solid rgba(255,255,255,.1);
    border-radius: 2px;
    box-shadow: 0 12px 34px rgba(0,0,0,.42);
    padding: 10px 0;
    z-index: 120;
  }
  /* Puente invisible entre el botón y el panel: sin esto el menú se cierra
     al cruzar los 14px de aire y el hover se vuelve inusable. */
  .nav__dd-menu::before {
    content: '';
    position: absolute;
    top: -14px; left: 0; right: 0;
    height: 14px;
  }
  .nav__dd-link { padding: 9px 20px; }
  .nav__dd-link:hover { background: rgba(255,255,255,.05); }
  .nav__dd-sep {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid rgba(255,255,255,.09);
  }
}

/* ── Bajo 1200px: lista dentro del menú hamburguesa ── */
@media (max-width: 1199px) {
  .nav__dd { width: 100%; }
  .nav__dd-btn {
    width: 100%;
    justify-content: space-between;
    font-size: 1rem;
    color: var(--white);
    padding: 8px 0;
  }
  .nav__dd-menu {
    padding: 4px 0 10px 2px;
    border-left: 1px solid rgba(255,255,255,.12);
    margin-left: 2px;
  }
  .nav__dd-link { padding: 9px 0 9px 14px; font-size: .95rem; }
  .nav__dd-sep { margin-top: 4px; }
}

/* ═══ 3 · LOGO MÁS GRANDE ═══════════════════════════════════════════════

   42 → 50px en escritorio. Para que no aplaste la barra, la barra sube de
   72 a 80px: quedan 15px de aire arriba y abajo, que es lo que evita que
   el logo se lea encajado.

   En móvil se queda en 44px a propósito. A 50px, con el ancho intrínseco
   del archivo (159×42 → ratio 3,79), el logo mediría 189px; en una
   pantalla de 320px, descontando los 24px de padding del contenedor a cada
   lado, quedan 272px útiles y la hamburguesa necesita 26px más su aire.
   Cabe, pero justo. 44px → 167px deja margen real.

   El panel del menú móvil arranca en 80px, igual que la barra: si se
   quedaba en 72 aparecía una franja transparente entre los dos.

   ── DEFECTO PREEXISTENTE ENCONTRADO Y CORREGIDO AQUÍ ──────────────────
   Midiendo el respaldo del 2026-08-19 apareció esto, y NO lo introdujo
   esta tanda: `.nav__logo` es un hijo flex sin `flex`, así que el valor
   por defecto (`flex-shrink: 1`) lo dejaba encogerse cuando el menú no
   cabía. Anchos reales del logo en el sitio publicado:

       1440px → 155px   (bien)
       1100px → 143px   (ya recortado)
       1024px →  67px   (cortado a la mitad)
        960px →   3px   (el logo desaparecía)

   Es decir: en cualquier laptop de 1024 o 1366×768 escalado, el logo se
   veía mutilado. Se corrige con `flex: none` — el logo nunca se encoge.

   Pero eso solo traslada el problema: si el logo no cede, algo tiene que
   ceder, y el menú completo (ocho enlaces + dos botones ≈ 910px) más el
   logo simplemente NO CABEN por debajo de ~1200px. Por eso la
   hamburguesa, que hasta hoy aparecía por debajo de 860px, ahora aparece
   por debajo de 1200px: es el ancho a partir del cual el menú entra sin
   recortar nada. Preferimos un menú hamburguesa correcto a una barra que
   se ve rota. */
.nav__logo { flex: none; }
.nav__inner { height: 80px; }
.nav__logo img { height: 50px; }
.nav__menu.open { top: 80px; }
.nav__menu { gap: 28px; }

/* La hamburguesa se hace cargo hasta 1199px. La regla original vive en la
   línea 385 con `!important`, así que hay que anularla explícitamente en
   ese tramo — no basta con declarar el nuevo breakpoint más abajo. */
@media (max-width: 1199px) {
  .nav__menu:not(.open) { display: none !important; }
  .nav__toggle { display: flex; }
}
@media (min-width: 1200px) {
  .nav__menu { display: flex !important; }
  .nav__toggle { display: none; }
}

@media (max-width: 520px) {
  .nav__inner { height: 72px; }
  .nav__logo img { height: 44px; }
  .nav__menu.open { top: 72px; }
}

/* El hero es `position: fixed` por debajo del nav: 8px más de barra piden
   8px más de aire arriba para que el eyebrow no quede pegado. */
.hero { padding-top: 156px; }
@media (max-width: 760px) {
  .hero { padding-top: 128px; }
}


/* ═══ 4 · ANCLAS ENTRE PÁGINAS: QUE EL TÍTULO NO QUEDE BAJO LA BARRA ═════

   Encontrado al replicar el menú «Soluciones» en las páginas internas
   (2026-08-20). NO lo introdujo esa tanda: ya pasaba con «Industrias»,
   «Nosotros» y «Contáctenos», que apuntan a index.html#… desde hace días.

   Los dos caminos hasta una sección no son el mismo:

   · Clic DENTRO de la portada («#sol-telemetria»). Lo atiende el bloque 6
     de script.js, que resta la altura de la barra + 8px antes de hacer
     scroll. Queda bien.

   · Llegada DESDE OTRA PÁGINA («index.html#sol-telemetria»). Aquí no corre
     ese código: el navegador aplica su salto nativo, que alinea el elemento
     con el borde superior de la ventana. Y la barra es `position: fixed`
     con 80px de alto, así que el <h3> de la sección queda TAPADO. El
     visitante aterriza viendo un párrafo a media frase y concluye que el
     enlace lo dejó en el lugar equivocado.

   `scroll-padding-top` lo corrige de raíz y sin JavaScript: el navegador
   reserva ese espacio en CUALQUIER salto nativo — enlace entre páginas,
   recarga con hash, «Buscar en la página», navegación por teclado.

   No duplica el ajuste del bloque 6: `window.scrollTo()` con una posición
   calculada a mano ignora `scroll-padding`. Los dos caminos aterrizan en
   el mismo sitio.

   80px de barra + 16px de aire = 96. Bajo 520px la barra mide 72 → 88. */
html { scroll-padding-top: 96px; }
@media (max-width: 520px) {
  html { scroll-padding-top: 88px; }
}


/* ═══ 5 · BLOG DE RECURSOS ══════════════════════════════════════════════

   Añadido el 2026-08-20, cuando Recursos dejó de ser una página suelta con
   modales y pasó a ser un blog: `recursos.html` es el índice y cada
   artículo vive en su propio archivo dentro de `recursos/`.

   Dos partes:
     A · el índice — barra de filtros y tarjetas que ahora son enlaces.
     B · la página de artículo — cuerpo de lectura.

   No introduce ni un color, ni una fuente, ni un radio nuevos: todo sale
   de las variables de :root. El naranja de texto es `--orange-text`
   (#C0551D), el que pasa AA sobre blanco — no el naranja de marca, que
   solo se usa en iconos y elementos gráficos.

   Las clases `.rec-modal__*` NO se borraron: `index.html` las sigue usando
   para las fichas de marcas (bloque 10 de script.js). Solo dejó de usarlas
   `recursos.html`.
   ══════════════════════════════════════════════════════════════════════ */

/* ── A · ÍNDICE: BARRA DE FILTROS ──────────────────────────────────────
   La construye blog.js leyendo el `data-cat` de las tarjetas. En el HTML
   los dos contenedores van vacíos, así que sin JavaScript `:empty` los
   borra del flujo y no queda un hueco raro sobre la grilla. */
.blog-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 40px;
}
.blog-filters:empty { display: none; }

.blog-filter {
  font-family: var(--font-mono);
  font-size: .78rem;
  letter-spacing: .04em;
  color: var(--text-muted);
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-radius: 999px;
  padding: 8px 16px;
  transition: color var(--transition), border-color var(--transition), background var(--transition);
}
.blog-filter:hover {
  color: var(--text-dark);
  border-color: var(--gray-mid);
}
/* El estado activo es `aria-pressed`, no una clase: el dato que lee el
   lector de pantalla y el que pinta el CSS son el mismo, así que no
   pueden quedar desincronizados. */
.blog-filter[aria-pressed="true"] {
  color: var(--white);
  background: var(--charcoal);
  border-color: var(--charcoal);
}

.blog-filters__count {
  font-family: var(--font-mono);
  font-size: .74rem;
  letter-spacing: .04em;
  color: var(--text-muted);
  margin-top: 14px;
}
.blog-filters__count:empty { display: none; }

/* Con filtros arriba, la grilla ya no necesita su propio margen. */
.blog-filters + .blog-filters__count + .blog-grid { margin-top: 22px; }

/* ── A · ÍNDICE: LA TARJETA COMO ENLACE ────────────────────────────────
   Antes la tarjeta terminaba en un <button> que abría un modal. Ahora el
   enlace real es el título, y su `::after` se estira sobre toda la
   tarjeta para que se pueda pulsar en cualquier punto.

   Por qué así y no envolviendo la tarjeta entera en un <a>: un solo
   enlace por tarjeta. Con título, imagen y «Leer el artículo» enlazados
   por separado, quien navega con lector de pantalla oiría tres veces el
   mismo destino. El «Leer el artículo» de abajo es `aria-hidden` por la
   misma razón: es una señal visual, no un enlace más. */
.blog-card { position: relative; }

.blog-card__title {
  color: inherit;
  transition: color var(--transition);
}
.blog-card__title::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: var(--radius);
}
.blog-card:hover .blog-card__title { color: var(--orange-text); }

/* El foco del teclado se dibuja alrededor de la tarjeta y no del renglón
   del título: el área pulsable es la tarjeta, y el recuadro tiene que
   decir la verdad sobre lo que se va a activar con Enter. */
.blog-card__title:focus { outline: none; }
.blog-card:focus-within {
  outline: 2px solid var(--orange-text);
  outline-offset: 3px;
}

/* «Leer el artículo» ya no es un botón: es un <span> decorativo. La
   animación de la flecha tiene que colgar del hover de la TARJETA,
   porque el `::after` del título cubre el span y le roba el :hover. */
.blog-card__link { pointer-events: none; }
.blog-card:hover .blog-card__link { gap: 8px; }
.blog-card:hover .blog-card__link svg { transform: translateX(2px); }

/* ── A · ÍNDICE: MARCA DE «MUESTRA» ────────────────────────────────────
   Borde discontinuo y etiqueta: el relleno tiene que verse como relleno
   incluso de reojo, para que nadie lo confunda con contenido publicable.
   Todo este bloque se puede borrar el día que se vayan las dos tarjetas
   de muestra. */
.blog-card--muestra { border-style: dashed; }
.blog-card__badge {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--gray-bg);
  border: 1px solid var(--gray-border);
  font-family: var(--font-mono);
  font-size: .62rem;
  letter-spacing: .08em;
  color: var(--text-muted);
  vertical-align: 1px;
}

/* ── B · PÁGINA DE ARTÍCULO: ENCABEZADO ────────────────────────────────
   Reusa `.page-hero` (fondo charcoal, migas, mismo aire). Lo único que
   cambia es el tamaño del <h1>: el de las otras páginas llega a 3.2rem,
   que sirve para «Trayectoria» pero no para un titular de nueve palabras
   — a ese tamaño ocupa media pantalla y empuja el artículo fuera de la
   vista.

   El encabezado se centra junto con el cuerpo (ver el bloque de la
   columna de lectura, más abajo): migas, categoría, titular y firma
   caen exactamente sobre el mismo eje que el texto del artículo. */
.post-hero h1 {
  font-size: clamp(1.65rem, 3.2vw, 2.5rem);
}
.post-hero__cat {
  font-family: var(--font-mono);
  font-size: .72rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--orange);
  margin-bottom: 14px;
}
.post-hero__meta {
  font-family: var(--font-mono);
  font-size: .76rem;
  letter-spacing: .03em;
  color: rgba(255,255,255,.55);
  margin-top: 18px;
}

/* ── B · PÁGINA DE ARTÍCULO: CUERPO ────────────────────────────────────
   Ancho de lectura en `--post-measure` (ver :root). */
.post-section {
  background: var(--white);
  padding: var(--section-py) 0;
}

/* ── B · LA COLUMNA DE LECTURA ─────────────────────────────────────────
   2026-08-21. Antes cada pieza del artículo llevaba `max-width: 68ch`
   pero ninguna llevaba margen automático, así que la columna quedaba
   pegada al borde izquierdo del contenedor de 1180px y sobraban 476px
   de blanco a la derecha. Se veía como una página a medio maquetar.
   Julián lo pidió centrado.

   Se centra el bloque, NO el texto: `margin-inline: auto` y nada de
   `text-align: center`. Un párrafo centrado obliga al ojo a buscar
   dónde empieza cada renglón.

   Se aplica a los hijos directos de `.container` en las dos zonas del
   artículo —encabezado y cuerpo— para que titular, firma, figuras y
   texto compartan eje sin tener que tocar el HTML de los seis archivos. */
.post-hero .container > *,
.post-section .container > * {
  max-width: var(--post-measure);
  margin-inline: auto;
}

.post__fig {
  margin: 0 auto 40px;
  border: 1px solid var(--gray-border);
  border-radius: var(--radius);
  overflow: hidden;
}

.post { max-width: var(--post-measure); }

.post__lead {
  font-size: 1.14rem;
  line-height: 1.6;
  color: var(--text-dark);
  margin-bottom: 20px;
}
.post p {
  color: var(--text-body);
  margin-bottom: 18px;
}
.post h2 {
  font-size: var(--fs-h3);
  letter-spacing: var(--ls-tight);
  margin-top: 44px;
  margin-bottom: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--gray-border);
}
.post ul {
  list-style: none;
  margin: 0 0 24px;
  padding: 0;
}
.post ul li {
  position: relative;
  padding-left: 22px;
  margin-bottom: 14px;
  color: var(--text-body);
}
.post ul li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: .62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--orange);
}

/* El disclaimer y el aviso de muestra se alinean con la columna de texto. */
.post-section .blog-disclaimer { max-width: var(--post-measure); margin-inline: auto; }

/* ── B · AVISO DE ARTÍCULO DE MUESTRA ──────────────────────────────────
   Se ve antes que nada, arriba del todo, en naranja tenue. Se va con los
   dos archivos `recursos/muestra-*.html`. */
.post__aviso {
  max-width: var(--post-measure);
  margin: 0 auto 32px;
  padding: 16px 20px;
  background: var(--orange-faint);
  border: 1px dashed var(--orange);
  border-radius: var(--radius-sm);
  font-size: .9rem;
  line-height: 1.6;
  color: var(--text-body);
}
.post__aviso code {
  font-family: var(--font-mono);
  font-size: .84em;
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-radius: 4px;
  padding: 1px 5px;
}

/* ── B · PIE DEL ARTÍCULO ──────────────────────────────────────────────
   Salida explícita al índice. Quien llega a un artículo desde Google o
   desde un enlace de WhatsApp no trae historial: sin esto, la única vía
   de vuelta es la barra de navegación. */
.post__foot {
  max-width: var(--post-measure);
  margin-inline: auto;
  margin-top: 36px;
  padding-top: 24px;
  border-top: 1px solid var(--gray-border);
}
.post__back {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: .86rem;
  font-weight: 600;
  color: var(--orange-text);
  transition: gap var(--transition), color var(--transition);
}
.post__back:hover {
  gap: 10px;
  color: var(--orange-dark);
}

@media (max-width: 639px) {
  .post-section { padding: var(--section-py-sm) 0; }
  .post__fig { margin-bottom: 28px; }
  .post h2 { margin-top: 34px; }
}


/* ═══ 5 · PÁGINAS DE SOLUCIÓN ════════════════════════════════════════════
   Añadido 2026-08-21, cuando las siete soluciones que vivían como anclas
   de la portada pasaron a tener página propia (la auditoría lo pedía:
   «#soluciones y #sectores son secciones, no páginas… todo el peso recae
   en una sola página que intenta rankear para todo a la vez»).

   La plantilla de referencia es ia-privada.html y NO se inventa paleta ni
   tipografía: todo sale de las variables de :root. Lo único nuevo aquí es
   el chrome compartido de los ejemplos interactivos (.sdemo) y dos
   utilidades de fondo para alternar negro / gris claro / blanco.

   ⚠️ CSP: `style-src 'self'` sin 'unsafe-inline'. Nada de style="…" en el
   HTML de estas páginas; todo estado visual se conmuta por clase o por el
   atributo [hidden] desde script.js (bloque 16).
   ══════════════════════════════════════════════════════════════════════ */

/* ── A · Franjas de sección ──────────────────────────────────────────── */
.sol-band          { padding: var(--section-py) 0; }
.sol-band--gray    { background: var(--gray-bg); }
.sol-band--white   { background: var(--white); }
.sol-band--dark    { background: var(--charcoal); }
.sol-band--dark h2,
.sol-band--dark h3 { color: var(--white); }
.sol-band--dark p  { color: var(--text-on-dark); }
.sol-band--dark .section-header p { color: rgba(255,255,255,.7); }

/* Columnas de texto con regla superior — mismo patrón que .gf-cols de la
   portada, pero con tres o cuatro por fila según quepa. */
.sol-cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: 34px 40px;
  margin-top: 44px;
}
@media (min-width: 700px)  { .sol-cols { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .sol-cols--3 { grid-template-columns: repeat(3, 1fr); } }
.sol-col {
  padding-top: 20px;
  border-top: 2px solid var(--orange);
}
.sol-band--dark .sol-col { border-top-color: var(--orange); }
.sol-col h3 {
  font-size: 1.08rem;
  font-weight: 700;
  margin-bottom: 10px;
  line-height: 1.32;
}
.sol-col p {
  font-size: .95rem;
  line-height: 1.7;
  color: var(--text-muted);
}
.sol-band--dark .sol-col p { color: var(--text-on-dark); }

/* Lista larga en prosa: la estructura de artículo que ya usa el blog
   (afirmación · dos puntos · consecuencia). */
.sol-points {
  max-width: 68ch;
  margin-top: 30px;
  display: grid;
  gap: 18px;
}
.sol-points li {
  position: relative;
  padding-left: 26px;
  font-size: 1rem;
  line-height: 1.75;
  color: var(--text-body);
}
.sol-points li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .68em;
  width: 12px;
  height: 2px;
  background: var(--orange);
}
.sol-points strong { color: var(--text-dark); font-weight: 600; }
.sol-lead {
  max-width: 68ch;
  font-size: 1.08rem;
  line-height: 1.75;
  color: var(--text-body);
}
.sol-lead + .sol-lead { margin-top: 18px; }

/* Nota de alcance: para decir en voz clara qué NO cubre una solución.
   Es una pieza de honestidad, no un descargo legal — va con el mismo
   registro sobrio del resto del sitio. */
.sol-scope {
  max-width: 68ch;
  margin-top: 36px;
  padding: 18px 22px;
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-left: 3px solid var(--gray-mid);
  border-radius: var(--radius-sm);
  font-size: .92rem;
  line-height: 1.7;
  color: var(--text-muted);
}
.sol-scope strong { color: var(--text-dark); font-weight: 600; }

/* ── B · Chrome compartido de los ejemplos interactivos ──────────────────
   Mismo lenguaje que .ia-viz de la página de IA privada: barra superior
   monoespaciada, escenario, pie explicativo y nota de «ilustrativo».
   Se le da nombre propio (.sdemo) para no acoplar siete páginas nuevas a
   las reglas de una que puede cambiar por su cuenta. */
.sdemo {
  margin-top: 44px;
  background: var(--white);
  border: 1px solid var(--gray-border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.sdemo__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 18px;
  background: var(--charcoal);
}
.sdemo__label {
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: rgba(255,255,255,.62);
}
.sdemo__toggle {
  font-family: var(--font-mono);
  font-size: .7rem;
  letter-spacing: .06em;
  font-weight: 500;
  color: var(--white);
  background: transparent;
  border: 1px solid rgba(255,255,255,.32);
  border-radius: 999px;
  padding: 7px 15px;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.sdemo__toggle:hover      { border-color: var(--orange); color: var(--orange-light); }
.sdemo__toggle:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
.sdemo__toggle[aria-pressed="true"] {
  background: var(--orange);
  border-color: var(--orange);
  color: var(--white);
}
.sdemo__stage  { padding: 26px 20px 22px; }
@media (min-width: 700px) { .sdemo__stage { padding: 32px 30px 26px; } }
.sdemo__caption {
  padding: 0 20px 16px;
  font-size: .9rem;
  line-height: 1.65;
  color: var(--text-body);
}
@media (min-width: 700px) { .sdemo__caption { padding: 0 30px 18px; } }
.sdemo__note {
  padding: 13px 20px;
  border-top: 1px solid var(--gray-border);
  background: var(--gray-bg);
  font-family: var(--font-mono);
  font-size: .7rem;
  line-height: 1.6;
  letter-spacing: .02em;
  color: var(--text-muted);
}
@media (min-width: 700px) { .sdemo__note { padding: 13px 30px; } }
.sdemo__kicker {
  font-size: .95rem;
  line-height: 1.7;
  color: var(--text-muted);
  max-width: 68ch;
  margin-top: 40px;
}
.sdemo__kicker + .sdemo { margin-top: 16px; }

/* Rejilla de dos escenarios lado a lado (antes / después, con / sin) */
.sdemo__pair {
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
}
@media (min-width: 780px) { .sdemo__pair { grid-template-columns: 1fr 1fr; gap: 22px; } }
.sdemo__panel {
  border: 1px solid var(--gray-border);
  border-radius: var(--radius-sm);
  padding: 18px;
  background: var(--white);
}
.sdemo__panel--bad  { border-color: rgba(190,60,40,.32); background: rgba(190,60,40,.035); }
.sdemo__panel--good { border-color: rgba(223,106,46,.34); background: var(--orange-faint); }
.sdemo__panel-title {
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--text-muted);
  display: block;
  margin-bottom: 14px;
}
.sdemo__panel--bad  .sdemo__panel-title { color: #A33520; }
.sdemo__panel--good .sdemo__panel-title { color: var(--orange-text); }
.sdemo__verdict {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--gray-border);
  font-size: .88rem;
  line-height: 1.6;
  color: var(--text-body);
}
.sdemo__verdict strong { color: var(--text-dark); font-weight: 600; }

/* Filas de datos monoespaciadas (registros, medidores, inventario) */
.sdemo__rows { display: grid; gap: 1px; background: var(--gray-border); border: 1px solid var(--gray-border); border-radius: var(--radius-sm); overflow: hidden; }
.sdemo__row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 10px 14px;
  padding: 11px 14px;
  background: var(--white);
}
@media (min-width: 620px) { .sdemo__row { grid-template-columns: 1.4fr 1fr auto; } }
.sdemo__row-name {
  font-size: .88rem;
  font-weight: 600;
  color: var(--text-dark);
  line-height: 1.4;
}
.sdemo__row-sub {
  display: block;
  font-weight: 400;
  font-size: .78rem;
  color: var(--text-muted);
  margin-top: 2px;
}
.sdemo__val {
  font-family: var(--font-mono);
  font-size: .92rem;
  font-weight: 500;
  color: var(--text-dark);
  letter-spacing: -.01em;
  transition: color 260ms var(--ease);
}
.sdemo__val--drift   { color: #A33520; }
.sdemo__val--aligned { color: var(--orange-text); }
.sdemo__val--none    { color: var(--gray-light); }
.sdemo__tag {
  justify-self: start;
  font-family: var(--font-mono);
  font-size: .64rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid var(--gray-border);
  color: var(--text-muted);
  white-space: nowrap;
}
.sdemo__tag--bad  { color: #A33520; border-color: rgba(190,60,40,.34); background: rgba(190,60,40,.06); }
.sdemo__tag--good { color: var(--orange-text); border-color: rgba(223,106,46,.34); background: var(--orange-faint); }

/* Barras de magnitud (balance de agua, capacidad) */
.sdemo__bars { display: grid; gap: 16px; }
.sdemo__bar-row { display: grid; gap: 7px; }
.sdemo__bar-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-size: .86rem;
  color: var(--text-body);
}
.sdemo__bar-head b { font-weight: 600; color: var(--text-dark); }
.sdemo__bar-head span {
  font-family: var(--font-mono);
  font-size: .86rem;
  color: var(--text-dark);
}
.sdemo__bar-track {
  display: block;   /* es un <span>: sin esto el ancho del relleno no aplica */
  height: 14px;
  border-radius: 999px;
  background: var(--gray-bg);
  border: 1px solid var(--gray-border);
  overflow: hidden;
}
.sdemo__bar-fill {
  display: block;   /* íd. — ver la nota de .sdemo__bar-track */
  height: 100%;
  background: var(--orange);
  border-radius: 999px;
  transition: width 420ms var(--ease), background 260ms var(--ease);
}
.sdemo__bar-fill--muted   { background: var(--gray-light); }
.sdemo__bar-fill--unknown {
  background: repeating-linear-gradient(45deg, var(--gray-border) 0 6px, var(--gray-bg) 6px 12px);
}
.sdemo__bar-fill--loss    { background: #A33520; }

/* Plano de cobertura: rejilla de celdas que cambian de intensidad */
.sdemo__plan {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 4px;
  max-width: 560px;
}
.sdemo__cell {
  aspect-ratio: 1;
  border-radius: 2px;
  background: var(--gray-border);
  transition: background 320ms var(--ease);
}
.sdemo__cell--s3 { background: var(--orange); }
.sdemo__cell--s2 { background: rgba(223,106,46,.55); }
.sdemo__cell--s1 { background: rgba(223,106,46,.24); }
.sdemo__cell--s0 { background: #D8D2CF; }
.sdemo__cell--ap { background: var(--charcoal); border-radius: 50%; }
.sdemo__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin-top: 14px;
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.sdemo__legend span { display: inline-flex; align-items: center; gap: 6px; }
.sdemo__swatch { width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
.sdemo__swatch--s3 { background: var(--orange); }
.sdemo__swatch--s1 { background: rgba(223,106,46,.24); }
.sdemo__swatch--s0 { background: #D8D2CF; }
.sdemo__swatch--ap { background: var(--charcoal); border-radius: 50%; }

/* Línea de tiempo de un incidente (mantenimiento) */
.sdemo__tl { display: grid; gap: 0; }
.sdemo__tl-step {
  display: grid;
  grid-template-columns: 62px 1fr;
  gap: 14px;
  padding: 12px 0;
  border-top: 1px solid var(--gray-border);
}
.sdemo__tl-step:first-child { border-top: none; }
.sdemo__tl-when {
  font-family: var(--font-mono);
  font-size: .74rem;
  letter-spacing: .04em;
  color: var(--text-muted);
  padding-top: 2px;
}
.sdemo__tl-what { font-size: .9rem; line-height: 1.6; color: var(--text-body); }
.sdemo__tl-what b { color: var(--text-dark); font-weight: 600; }
.sdemo__tl-step--hit .sdemo__tl-when { color: #A33520; }
.sdemo__tl-step--hit .sdemo__tl-what b { color: #A33520; }
.sdemo__tl-step--win .sdemo__tl-when { color: var(--orange-text); }
.sdemo__tl-step--win .sdemo__tl-what b { color: var(--orange-text); }

/* Zonas de red (segmentación) */
.sdemo__zones { display: grid; gap: 12px; }
@media (min-width: 620px) { .sdemo__zones { grid-template-columns: repeat(3, 1fr); } }
.sdemo__zone {
  border: 1px dashed var(--gray-border);
  border-radius: var(--radius-sm);
  padding: 14px;
  background: var(--white);
  transition: border-color 300ms var(--ease), background 300ms var(--ease);
}
.sdemo__zone--split { border-style: solid; border-color: rgba(223,106,46,.4); }
.sdemo__zone--hit   { border-color: rgba(190,60,40,.45); background: rgba(190,60,40,.06); }
.sdemo__zone-name {
  font-family: var(--font-mono);
  font-size: .66rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-muted);
  display: block;
  margin-bottom: 8px;
}
.sdemo__zone ul { display: grid; gap: 5px; }
.sdemo__zone li { font-size: .84rem; color: var(--text-body); line-height: 1.45; }
.sdemo__zone-state {
  display: block;
  margin-top: 10px;
  font-family: var(--font-mono);
  font-size: .66rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.sdemo__zone--hit .sdemo__zone-state   { color: #A33520; }
.sdemo__zone--split .sdemo__zone-state { color: var(--orange-text); }

/* Control de rango (densidad de usuarios) */
.sdemo__control {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
  margin-bottom: 22px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--gray-border);
}
.sdemo__control label {
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.sdemo__control input[type="range"] { flex: 1 1 180px; min-width: 150px; accent-color: var(--orange); }
.sdemo__control output {
  font-family: var(--font-mono);
  font-size: .95rem;
  font-weight: 600;
  color: var(--text-dark);
  min-width: 6ch;
}

/* ── C · Sin JavaScript ─────────────────────────────────────────────────
   Los botones de los ejemplos son <button> reales: sin JS no conmutan.
   Cada ejemplo se sirve en su estado por defecto, que ya se entiende solo
   —igual que el diagrama de ia-privada.html—, y el texto de la página
   nunca depende de haber pulsado nada. */

/* El ancho de las barras del balance de agua se conmuta por custom
   property (--w) desde script.js, bloque 16.7. Así el HTML servido no
   lleva ningún atributo style —que `style-src 'self'` bloquearía— y el
   valor por defecto deja la barra vacía si el JS no corre. */
.sdemo__bar-fill { width: var(--w, 0%); }

/* ════════════════════════════════════════════════════════════
   19 · PIEZAS GRÁFICAS DE LOS CASOS DE ÉXITO  (.cviz)
   ════════════════════════════════════════════════════════════
   2026-08-21. Tres artículos de la categoría «Casos de éxito»
   llevan cada uno una figura construida con SVG y CSS de este
   mismo archivo: sin librerías, sin imágenes generadas y sin
   una sola declaración en línea.

   El lenguaje visual es DELIBERADAMENTE el de `.ia-viz`
   (bloque 18): fondo charcoal, barra superior con etiqueta en
   IBM Plex Mono, borde punteado para los límites, acento cobre
   `--orange` y pie de figura en mono. Se escribe aparte y no se
   reutiliza `.ia-viz` porque aquello es una topología de tres
   nodos en fila y esto son tres diagramas de forma distinta;
   compartir clases habría obligado a llenar `.ia-viz` de
   excepciones y a arriesgar la página de IA privada cada vez
   que se tocara un caso.

   ── CSP ──────────────────────────────────────────────────────
   `style-src 'self'` sin 'unsafe-inline': ningún atributo
   `style=` en el HTML servido. Todo lo que cambia de estado
   cambia por CLASE en el elemento raíz `.cviz` (la pone
   `casos.js`), nunca escribiendo estilos desde JavaScript.
   `script-src 'self'`: los botones son <button> reales y sus
   escuchas viven en `casos.js`, nunca en un `onclick=`.

   ── Sin JavaScript ───────────────────────────────────────────
   Cada figura se sirve en un estado por defecto que se entiende
   solo (operación normal · mapa predictivo · año 2025) y el
   texto del artículo no depende de haber pulsado nada. El botón
   simplemente no conmuta.

   ── Ancho ────────────────────────────────────────────────────
   El cuerpo del artículo vive en `--post-measure` (33rem). Una
   figura de 33rem deja los treinta switches del caso 1 en un
   sello ilegible, así que la figura —y solo ella— se ensancha a
   44rem sin salirse del `.container` ni romper el eje central:
   sigue con `margin-inline: auto`.
   ════════════════════════════════════════════════════════════ */

.cviz {
  background: var(--charcoal);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 2px;
  margin: 44px auto 48px;
  overflow: hidden;
}

/* Gana por especificidad a `.post-section .container > *`
   (3 clases contra 2). Ver la nota de ancho, arriba. */
.post-section .container > .cviz { max-width: 44rem; }

.cviz__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 10px 20px;
  background: rgba(255,255,255,.04);
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.cviz__label {
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: var(--ls-eyebrow);
  color: rgba(255,255,255,.35);
}
.cviz__toggle {
  font-family: var(--font-mono);
  font-size: .72rem;
  color: var(--orange);
  background: none;
  border: 1px solid rgba(223,106,46,.35);
  border-radius: 2px;
  padding: 5px 14px;
  cursor: pointer;
  transition: background 180ms var(--ease), border-color 180ms var(--ease);
  white-space: nowrap;
}
.cviz__toggle:hover,
.cviz__toggle[aria-pressed="true"] {
  background: rgba(223,106,46,.1);
  border-color: rgba(223,106,46,.6);
}
.cviz__toggle:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

.cviz__stage { padding: 24px 18px 18px; }
@media (min-width: 700px) { .cviz__stage { padding: 30px 26px 20px; } }
.cviz__svg { display: block; width: 100%; height: auto; }

/* Pie de figura. Cada figura trae UNA nota por estado y el CSS
   enseña la que corresponde: así el texto del pie no lo escribe
   JavaScript y sigue estando en el HTML servido. */
.cviz__caption {
  font-size: .78rem;
  line-height: 1.55;
  color: rgba(255,255,255,.34);
  font-family: var(--font-mono);
  letter-spacing: .02em;
  padding: 14px 20px 20px;
  margin: 0;
  border-top: 1px solid rgba(255,255,255,.05);
}
.cviz__caption b { color: rgba(255,255,255,.62); font-weight: 500; }
.cviz__note-b { display: none; }
.cviz.is-alt .cviz__note-a { display: none; }
.cviz.is-alt .cviz__note-b { display: block; }

/* ── Vocabulario común de los tres SVG ──────────────────────── */
.cviz-boundary {
  fill: none;
  stroke: rgba(255,255,255,.18);
  stroke-width: 1;
  stroke-dasharray: 5 4;
}
.cviz-tag {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: .12em;
  fill: rgba(255,255,255,.3);
}
.cviz-name {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .04em;
  fill: rgba(255,255,255,.66);
}
.cviz-num {
  font-family: var(--font-mono);
  font-size: 26px;
  font-weight: 600;
  fill: rgba(255,255,255,.75);
}
.cviz-box {
  fill: rgba(255,255,255,.05);
  stroke: rgba(255,255,255,.14);
  stroke-width: 1;
}
.cviz-box--core {
  fill: rgba(223,106,46,.08);
  stroke: rgba(223,106,46,.42);
}
.cviz-link {
  fill: none;
  stroke: rgba(255,255,255,.18);
  stroke-width: 1.5;
}

/* ── CASO 1 · capas y redundancia ───────────────────────────── */
/* Los dos caminos entre capas. El B se sirve activo igual que el
   A: en operación normal los dos llevan tráfico, que es lo que
   dice el texto («redundancia física y lógica»). */
.cviz-trunk { fill: none; stroke: var(--orange); stroke-width: 2.5; stroke-linecap: round; }
.cviz-flow  { fill: var(--orange); }
.cviz-fail  { opacity: 0; }

/* Estado «enlace caído»: el camino A queda punteado y apagado,
   aparece la marca de corte y el B se refuerza. El tráfico sigue.
   Nada de esto lo escribe JavaScript: solo pone `is-alt`. */
.cviz.is-alt .cviz-trunk--a {
  stroke: rgba(255,255,255,.16);
  stroke-width: 1.5;
  stroke-dasharray: 4 5;
}
/* Se apaga la ANIMACIÓN además de la opacidad. Sin lo primero el punto
   sigue viéndose: los fotogramas de `cviz-down` fijan `opacity: 1` y una
   animación en curso gana sobre una declaración normal. Se vio en la
   verificación del 2026-08-21 — el camino cortado seguía con tráfico. */
.cviz.is-alt .cviz-flow--a { animation: none; opacity: 0; }
.cviz.is-alt .cviz-fail    { opacity: 1; }
.cviz.is-alt .cviz-trunk--b { stroke-width: 3.5; }
.cviz-x { stroke: #dc2626; stroke-width: 2; stroke-linecap: round; }
.cviz-x-text {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: .1em;
  fill: rgba(220,38,38,.8);
}

/* Punto de tráfico bajando por el camino. `translate` sobre un
   elemento SVG: no toca la geometría del documento y se apaga
   entero con `prefers-reduced-motion` (más abajo). */
@keyframes cviz-down {
  0%   { transform: translateY(0);     opacity: 0; }
  10%  { opacity: 1; }
  90%  { opacity: 1; }
  100% { transform: translateY(104px); opacity: 0; }
}
.cviz-flow { animation: cviz-down 2.1s linear infinite; }
.cviz-flow--b1 { animation-delay: .7s; }
.cviz-flow--a1 { animation-delay: 1.4s; }

/* ── CASO 2 · mapa de calor ─────────────────────────────────── */
.cviz-cell   { stroke: rgba(17,17,17,.55); stroke-width: .5; }
.cviz-cell--s3 { fill: #DF6A2E; }
.cviz-cell--s2 { fill: rgba(223,106,46,.58); }
.cviz-cell--s1 { fill: rgba(223,106,46,.26); }
.cviz-cell--s0 { fill: rgba(255,255,255,.07); }
.cviz-ap     { fill: var(--charcoal); stroke: rgba(255,255,255,.85); stroke-width: 1.4; }
.cviz-ap-txt { font-family: var(--font-mono); font-size: 8px; fill: rgba(255,255,255,.9); }
.cviz-legend { font-family: var(--font-mono); font-size: 9px; letter-spacing: .08em; fill: rgba(255,255,255,.36); }

/* Conmutación de estados: el HTML sirve los dos y el CSS decide.
   Se hace con `display` y no con el atributo `hidden` para que un
   navegador sin JS vea siempre el predictivo, que es el estado que
   el texto describe primero. */
.cviz__state--b { display: none; }
.cviz.is-alt .cviz__state--a { display: none; }
.cviz.is-alt .cviz__state--b { display: block; }

/* ── CASO 3 · escala geográfica y salto de alcance ──────────── */
.cviz-cr    { fill: rgba(255,255,255,.045); stroke: rgba(255,255,255,.2); stroke-width: 1; }
.cviz-gam   { fill: rgba(223,106,46,.05); stroke: rgba(255,255,255,.28); stroke-width: 1; stroke-dasharray: 4 4; }
.cviz-site  { fill: rgba(255,255,255,.22); transition: fill 220ms var(--ease), r 220ms var(--ease); }
.cviz-site-txt { font-family: var(--font-mono); font-size: 9px; letter-spacing: .03em; fill: rgba(255,255,255,.32); transition: fill 220ms var(--ease); }
/* `fill: none` no es decorativo: un <polyline> sin él se rellena de negro
   por defecto y la línea guía sale como una mancha. Visto en la
   verificación del 2026-08-21. */
.cviz-lead  { fill: none; stroke: rgba(255,255,255,.2); stroke-width: 1; }

/* 2025 (por defecto) enciende los sitios de fuera de la GAM;
   2026 enciende los de dentro. El texto dice «principalmente» y
   «la mayoría», nunca «solo»: por eso los apagados no desaparecen,
   se atenúan. */
.cviz-site--fuera { fill: var(--orange); }
.cviz-site--fuera + .cviz-site-txt { fill: rgba(255,255,255,.72); }
.cviz.is-alt .cviz-site--fuera { fill: rgba(255,255,255,.22); }
.cviz.is-alt .cviz-site--fuera + .cviz-site-txt { fill: rgba(255,255,255,.32); }
.cviz.is-alt .cviz-site--gam { fill: var(--orange); }
.cviz.is-alt .cviz-site--gam + .cviz-site-txt { fill: rgba(255,255,255,.72); }

.cviz-bar-track { fill: rgba(255,255,255,.07); }
.cviz-bar-fill  { fill: rgba(255,255,255,.13); transition: fill 220ms var(--ease); }
.cviz-bar-fill--2025 { fill: var(--orange); }
.cviz.is-alt .cviz-bar-fill--2025 { fill: rgba(255,255,255,.13); }
.cviz.is-alt .cviz-bar-fill--2026 { fill: var(--orange); }
.cviz-chip {
  fill: none;
  stroke: rgba(223,106,46,.3);
  stroke-width: 1;
}
.cviz-chip-txt { font-family: var(--font-mono); font-size: 9px; letter-spacing: .06em; fill: rgba(223,106,46,.85); }

/* ── prefers-reduced-motion — NO NEGOCIABLE ──────────────────
   Se apaga el único movimiento continuo que hay (el punto que
   baja por el camino) y las transiciones de color de los tres
   diagramas. Los botones siguen conmutando: la persona cambia de
   estado cuando quiere, que es justamente lo que la preferencia
   pide — quitar el movimiento que no se pidió, no la interacción.
   Sin el punto animado el diagrama no pierde información: los dos
   caminos se distinguen por trazo continuo contra punteado. */
@media (prefers-reduced-motion: reduce) {
  .cviz-flow { animation: none; }
  .cviz-site,
  .cviz-site-txt,
  .cviz-bar-fill,
  .cviz__toggle { transition: none; }
}

/* ── Móvil ──────────────────────────────────────────────────── */
@media (max-width: 560px) {
  .cviz__bar { padding: 10px 14px; }
  .cviz__stage { padding: 18px 12px 14px; }
  .cviz__caption { padding: 12px 14px 16px; font-size: .74rem; }
  .cviz__toggle { width: 100%; text-align: center; }
}


/* ════════════════════════════════════════════════════════════
   20 · PROTOTIPO — HERO CON DIAGRAMA (2026-08-24)
   ════════════════════════════════════════════════════════════
   Solo lo usa `mantenimiento-y-continuidad.html`, con la clase
   `.page-hero--viz`. Todo cuelga de ese modificador: sin él, el
   `.page-hero` de las otras catorce páginas se comporta igual
   que ayer. Este bloque se AÑADE al final y no modifica ninguna
   regla anterior — misma disciplina del bloque 19.

   Lenguaje visual tomado de `.ia-viz`: fondo charcoal, barra de
   rótulo en mono, borde de 1px a muy baja opacidad, acento cobre
   y línea punteada para lo que no se ve. Nada en línea: la CSP es
   `style-src 'self'` sin 'unsafe-inline', así que un `style=` en
   el SVG lo ignoraría el navegador EN SILENCIO — los colores van
   por clase y la geometría por atributo de presentación, que no
   es CSS y la CSP no toca.

   Si esto se aprueba para las otras siete, lo que hay que
   generalizar es de `.page-hero__grid` para abajo; `.hviz` es el
   diagrama de ESTA página y cada una necesitaría el suyo.
   ──────────────────────────────────────────────────────────── */

/* ── La retícula ────────────────────────────────────────────────
   Móvil primero y en una sola columna: así el titular queda
   SIEMPRE antes que el diagrama en el orden del documento, y a
   390px no hay manera de que el dibujo lo empuje fuera de la
   pantalla. Las dos columnas solo aparecen cuando hay ancho de
   sobra. El orden del DOM ya es el correcto — no se reordena con
   `order`, que dejaría el foco del teclado saltando. */
.page-hero--viz { padding-bottom: 56px; }

.page-hero__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 36px;
  align-items: center;
}
@media (min-width: 900px) {
  .page-hero__grid {
    /* minmax(0,·) en las dos: sin el 0 una pista `1fr` toma como
       mínimo el contenido, y un `<h1>` con palabras largas
       ensancharía la columna hasta desbordar el contenedor. */
    grid-template-columns: minmax(0, 1.12fr) minmax(0, .88fr);
    gap: 48px;
  }
}
/* El sub del hero está limitado a 640px para el hero ancho; en la
   columna angosta ese tope no aplica nunca y sobra decirlo, pero
   se deja explícito para que no dependa del ancho de la pista. */
.page-hero--viz .page-hero__sub { max-width: 46ch; }

/* El titular baja un punto respecto al `.page-hero h1` general.
   Motivo medido, no estético: el `<br>` del HTML parte el titular
   en dos líneas a propósito, y a 3.6rem «antes de que interrumpa.»
   no cabe en la columna izquierda — el navegador metía un salto
   extra y salían TRES líneas, con «interrumpa.» sola. A 2.95rem
   las dos líneas caben y el salto que manda es el del HTML.
   Si alguien cambia el texto del h1, hay que volver a mirar esto. */
.page-hero--viz h1 {
  font-size: clamp(2.1rem, 3.4vw, 2.95rem);
  max-width: none;
}

/* En una sola columna el diagrama no se estira: a 899px de ancho
   llegaba a 817px y el dibujo quedaba desparramado, con el eje de
   21 días ocupando media pantalla para decir lo mismo. Se le pone
   tope y se alinea a la izquierda, sobre el mismo eje del titular. */
@media (max-width: 899px) {
  .hviz { max-width: 560px; }
}

/* ── El diagrama ────────────────────────────────────────────── */
.hviz {
  margin: 0;
  background: rgba(255, 255, 255, .02);
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 2px;
  overflow: hidden;
}
.hviz__bar {
  padding: 9px 16px;
  background: rgba(255, 255, 255, .04);
  border-bottom: 1px solid rgba(255, 255, 255, .08);
}
.hviz__label {
  font-family: var(--font-mono);
  font-size: .66rem;
  letter-spacing: var(--ls-eyebrow);
  color: rgba(255, 255, 255, .35);
}
.hviz__svg {
  display: block;
  width: 100%;
  height: auto;
  padding: 14px 16px 6px;
  box-sizing: border-box;
}
.hviz__note {
  font-family: var(--font-mono);
  font-size: .62rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, .3);
  padding: 12px 16px 14px;
  border-top: 1px solid rgba(255, 255, 255, .05);
}

/* ── Eje compartido: es lo que hace que se lea «la misma línea» ─ */
.hviz__guides line {
  stroke: rgba(255, 255, 255, .1);
  stroke-width: 1;
  stroke-dasharray: 2 5;
}
.hviz__day {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: .1em;
  fill: rgba(255, 255, 255, .4);
}
.hviz__track-name {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: .12em;
  fill: rgba(255, 255, 255, .5);
}

/* ── Los dos recorridos ─────────────────────────────────────── */
.hviz__line { stroke-width: 2; fill: none; }
/* Punteado = tramo a ciegas. Es el mismo recurso con que `.ia-viz`
   dibuja un límite que no se ve. */
.hviz__line--blind { stroke: rgba(255, 255, 255, .16); stroke-dasharray: 3 6; }
.hviz__line--seen  { stroke: var(--orange); }
.hviz__line--calm  { stroke: rgba(223, 106, 46, .35); }

.hviz__mark { stroke-width: 1.5; }
.hviz__mark--start { fill: rgba(255, 255, 255, .06); stroke: rgba(255, 255, 255, .35); }
.hviz__mark--hit   { fill: var(--orange); stroke: none; }
.hviz__mark--none  { fill: none; stroke: rgba(223, 106, 46, .45); }

.hviz__window {
  fill: rgba(223, 106, 46, .12);
  stroke: var(--orange);
  stroke-width: 1.5;
}

/* La X del final del recorrido sin monitoreo. Rojo del sitio — el
   mismo con que `.ia-viz` marca «sus datos salen de la org.». */
.hviz__x line {
  stroke: #dc2626;
  stroke-width: 2.4;
  stroke-linecap: round;
}

/* ── Rótulos ────────────────────────────────────────────────── */
.hviz__cap {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .06em;
}
.hviz__cap--soft { fill: rgba(255, 255, 255, .34); }
.hviz__cap--good { fill: rgba(223, 106, 46, .85); }
.hviz__cap--bad  { fill: rgba(220, 38, 38, .8); }
.hviz__cap--mid  { font-size: 12px; letter-spacing: .04em; font-style: italic; }

/* ── El único movimiento: el instante en que alguien se entera ──
   Un anillo que late una vez cada 2,6s sobre la marca de detección
   del recorrido con monitoreo. No transporta información: la marca
   sólida ya está debajo y se ve igual con la animación apagada. */
.hviz__pulse {
  fill: none;
  stroke: var(--orange);
  stroke-width: 2;
  transform-origin: 70px 242px;
  animation: hviz-pulse 2.6s ease-out infinite;
}
@keyframes hviz-pulse {
  0%   { transform: scale(1);   opacity: .7; }
  70%  { transform: scale(2.6); opacity: 0; }
  100% { transform: scale(2.6); opacity: 0; }
}

/* ── prefers-reduced-motion — NO NEGOCIABLE ──────────────────
   Se apaga la animación Y se oculta el anillo. Solo apagar la
   animación dejaría el anillo congelado a opacidad .7 alrededor
   del punto, que es ruido, no información. Es exactamente el
   fallo que se corrigió en el bloque 19 el 2026-08-21. */
@media (prefers-reduced-motion: reduce) {
  .hviz__pulse { animation: none; opacity: 0; }
}

/* ── Móvil ──────────────────────────────────────────────────────
   A 390px el SVG se escala a ~0.63, así que los rótulos de 12px
   caerían a 7.6px — por debajo del piso del sitio (.58rem ≈ 9.3px
   en `.ia-viz__barrier-text`). En vez de encoger la letra hasta lo
   ilegible se quitan los rótulos secundarios y se sube el resto:
   quedan el eje, los nombres de los dos recorridos y las marcas,
   que es lo que sostiene la comparación. El texto completo sigue
   estando en el `<desc>` del SVG para quien use lector de pantalla
   y en el `.sdemo` de más abajo para todo el mundo. */
@media (max-width: 620px) {
  .page-hero__grid { gap: 26px; }
  .hviz__cap--mid { display: none; }
  .hviz__cap { font-size: 15px; }
  .hviz__day,
  .hviz__track-name { font-size: 15px; }
  .hviz__svg { padding: 14px 10px 6px; }
  .hviz__bar { padding: 9px 14px; }
  .hviz__note { padding: 10px 14px 12px; }
}


/* ════════════════════════════════════════════════════════════
   20.b · HERO CON DIAGRAMA — PRIMITIVAS COMPARTIDAS (2026-08-24)
   ════════════════════════════════════════════════════════════
   Segunda tanda del mismo día. El bloque 20 dejó el patrón montado
   en `mantenimiento-y-continuidad.html`; esto es lo que hizo falta
   para llevarlo a otras seis páginas de solución.

   Disciplina, la misma de siempre: este sub-bloque **solo añade**.
   Ni una regla del bloque 20 se tocó — `.hviz`, `.hviz__bar`,
   `.hviz__svg`, `.hviz__note`, las líneas, las marcas, los rótulos
   y el `@media (max-width: 620px)` de allá arriba siguen letra por
   letra como estaban, así que el hero de mantenimiento no puede
   haber cambiado. Lo de acá son PRIMITIVAS: cajas, celdas, barras,
   frontera y flechas. Cada página compone su dibujo con ellas y no
   necesita CSS propio; si mañana una lo necesitara, va en un 20.c
   y tampoco se toca nada de esto.

   Colores: `var(--orange)` y blanco/naranja con alfa, exactamente
   como el bloque 20. Ningún hex nuevo. El rojo aparece una sola vez
   y es el mismo `rgba(220, 38, 38, ·)` que ya usaba `.hviz__cap--bad`.

   CSP: nada en línea, igual que antes. `style-src 'self'` sin
   'unsafe-inline' — un `style=` en el SVG lo ignoraría el navegador
   EN SILENCIO. Los colores van por clase; la geometría (`x`, `cx`,
   `width`…) va en atributos de presentación, que son XML y la CSP
   no toca.
   ──────────────────────────────────────────────────────────── */

/* ── Variante de titular largo ──────────────────────────────────
   El `.page-hero--viz h1` del bloque 20 está calibrado para el
   titular de mantenimiento («La falla se atiende / antes de que
   interrumpa.»): dos líneas de 26 y 25 caracteres. Tres de las
   páginas nuevas tienen una línea más larga que eso —conectividad
   30, inventario 28, diagnóstico 27— y todas llevan un `<br>` que
   fuerza el corte. Si la primera línea no cabe, el navegador mete
   un salto extra y deja una palabra suelta: el mismo defecto que
   se corrigió el 2026-08-24 en mantenimiento.

   ⚠️ El tamaño de aquí sale de un CÁLCULO, no de una medición en
   navegador: la columna de texto mide ~634 px a 1440 (contenedor
   1180, gap 48, pista 1.12fr de 2fr) y IBM Plex Sans Light con
   -0.03em avanza ~0.49em por carácter, de modo que a 2.45rem
   entran ~33 caracteres y a 2.95rem solo ~27. Es holgura de
   sobra sobre los 30 del peor caso, pero conviene mirarlo en
   pantalla y ajustar si hiciera falta. Se aplica SOLO a las tres
   páginas que lo necesitan, con clase propia, para no mover el
   titular de las otras cuatro ni el de mantenimiento. */
.page-hero--viz-tight h1 {
  font-size: clamp(1.9rem, 2.9vw, 2.45rem);
}

/* ── Rótulos ────────────────────────────────────────────────────
   `.hviz__cap` (bloque 20) es el rótulo secundario. Faltaban dos
   registros: el nombre de un nodo, que tiene que leerse antes que
   el rótulo, y la cifra que el dibujo va a defender. */
.hviz__cap--strong { fill: rgba(255, 255, 255, .68); }
.hviz__figure {
  font-family: var(--font-mono);
  font-size: 21px;
  letter-spacing: .02em;
  fill: rgba(255, 255, 255, .82);
}
.hviz__figure--hot { fill: var(--orange); }
/* Mismo rojo que `.hviz__cap--bad`, un punto más presente porque
   la cifra pesa más que el rótulo. */
.hviz__figure--bad { fill: rgba(220, 38, 38, .9); }

/* ── Cajas y nodos ──────────────────────────────────────────────
   La caja neutra es el ladrillo de los diagramas de flujo (IA
   privada) y de las fichas de dato (inventario). La variante
   `--hot` es la que el dibujo quiere que se mire; la `--ghost`
   es el dato que NO se tiene: contorno punteado y sin relleno,
   el mismo recurso con que `.hviz__line--blind` dibuja un tramo
   a ciegas. */
.hviz__box {
  fill: rgba(255, 255, 255, .04);
  stroke: rgba(255, 255, 255, .18);
  stroke-width: 1;
}
.hviz__box--hot {
  fill: rgba(223, 106, 46, .10);
  stroke: var(--orange);
  stroke-width: 1.5;
}
.hviz__box--ghost {
  fill: none;
  stroke: rgba(255, 255, 255, .16);
  stroke-width: 1;
  stroke-dasharray: 3 5;
}

/* ── Frontera de organización (IA privada) ──────────────────────
   Es la traducción a SVG de `.ia-viz__boundary`: perímetro cobre
   punteado. Se mantiene punteado a propósito — un borde sólido se
   leería como un muro que detiene algo, y esta página no habla de
   detener nada, habla de que nada sale. */
.hviz__boundary {
  fill: rgba(223, 106, 46, .04);
  stroke: rgba(223, 106, 46, .5);
  stroke-width: 1.5;
  stroke-dasharray: 6 5;
}

/* ── Flechas de flujo ───────────────────────────────────────────
   La punta va como <marker> con clase propia: el `fill` de un
   marcador no se hereda del trazo que lo usa. */
.hviz__flow {
  fill: none;
  stroke: var(--orange);
  stroke-width: 2;
}
.hviz__arrowhead { fill: var(--orange); }

/* ── Planta y cobertura (conectividad, diagnóstico) ─────────────
   `.hviz__room` es el recinto; `.hviz__ap` el equipo dentro. Las
   celdas son la rejilla del mapa de calor: s3 fuerte, s2 media,
   s1 débil, s0 sin señal útil. Los cuatro niveles son los mismos
   del `.sdemo` de diagnóstico (bloque 16.4 de script.js) y el
   mismo orden de intensidad, traducido al fondo charcoal: allá
   el degradado sube hacia el naranja sobre claro, acá sube hacia
   el naranja sobre oscuro. `--s0` no es negro sino un gris muy
   apagado: negro puro sobre charcoal se leería como un agujero
   en la figura, no como una celda medida y descartada. */
.hviz__room {
  fill: rgba(255, 255, 255, .025);
  stroke: rgba(255, 255, 255, .14);
  stroke-width: 1;
}
.hviz__ap { fill: var(--orange); }
.hviz__ap--ring {
  fill: none;
  stroke: var(--orange);
  stroke-width: 1.5;
}
.hviz__cell { stroke: none; }
.hviz__cell--s3 { fill: rgba(223, 106, 46, .62); }
.hviz__cell--s2 { fill: rgba(223, 106, 46, .34); }
.hviz__cell--s1 { fill: rgba(223, 106, 46, .16); }
.hviz__cell--s0 { fill: rgba(255, 255, 255, .05); }

/* ── Barras de balance (telemetría) ─────────────────────────────
   La pista es el total; el relleno, lo medido. `--unknown` es la
   punta que no se mide: contorno punteado y hueco, para que se
   vea que ocupa lugar en el balance pero no tiene número.
   `--loss` es la resta entre las dos puntas — cobre atenuado,
   igual que `.hviz__line--calm`, porque es consecuencia de una
   medición, no una alarma. */
.hviz__meter-track {
  fill: rgba(255, 255, 255, .05);
  stroke: none;
}
.hviz__meter { fill: var(--orange); }
.hviz__meter--loss { fill: rgba(223, 106, 46, .38); }
.hviz__meter--unknown {
  fill: none;
  stroke: rgba(255, 255, 255, .22);
  stroke-width: 1;
  stroke-dasharray: 4 5;
}

/* ── Postes y cable (inventario) ────────────────────────────────
   El poste es una línea vertical corta con su base; el cable, el
   vano entre dos postes. Se dibuja con `.hviz__line--seen` /
   `--blind` del bloque 20, así que aquí solo hace falta el apoyo. */
.hviz__pole {
  stroke: rgba(255, 255, 255, .38);
  stroke-width: 2;
  stroke-linecap: round;
}

/* ── Móvil ──────────────────────────────────────────────────────
   El bloque 20 sube los rótulos a 15 unidades por debajo de 620 px
   (a 390 px el SVG se escala a ~0,63 y 12 px caerían a 7,6, por
   debajo del piso tipográfico del sitio). Las primitivas nuevas
   tienen que subir con ellos o se descuelgan de la jerarquía: la
   cifra dejaría de pesar más que su rótulo. Media query aparte,
   no se edita la de arriba. */
@media (max-width: 620px) {
  .hviz__figure { font-size: 25px; }
}

/* ============================================================
   MODAL DE POLÍTICA DE PRIVACIDAD — 2026-08-26
   Extiende .rec-modal. Caja más ancha y texto alineado a la
   izquierda, porque acá el contenido es un documento largo y no
   una ficha. El scroll lo hereda de .rec-modal__box (max-height
   90vh + overflow-y auto), así que la persona sube y baja dentro
   de la ventana sin salir de la página donde estaba.
   ============================================================ */
.rec-modal__box--doc {
  max-width: 720px;
  text-align: left;
  padding: 2.75rem 2rem 1.25rem;
  scroll-behavior: smooth;
}
.rec-modal__doc {
  text-align: left;
}
.rec-modal__doc h2,
.rec-modal__doc h3 {
  text-align: left;
}
.rec-modal__doc .legal__updated {
  margin-top: 0;
}
.rec-modal__doc-pie {
  position: sticky;
  bottom: 0;
  margin: 1.25rem -2rem 0;
  padding: .85rem 2rem;
  background: #fff;
  border-top: 1px solid var(--gray-border, #e5e5e5);
  text-align: right;
  font-size: .9rem;
}
@media (max-width: 640px) {
  .rec-modal__box--doc { padding: 2.5rem 1.25rem 1rem; }
  .rec-modal__doc-pie  { margin: 1rem -1.25rem 0; padding: .8rem 1.25rem; }
}

/* Escala del documento dentro del modal — 2026-08-26.
   La política se maqueta para página completa, donde un h2 grande ordena
   la lectura. Dentro de una caja de 720px ese mismo h2 se come la ventana
   (se vio en la primera prueba: el título ocupaba tres líneas y empujaba
   el texto fuera de vista). Acá se baja la jerarquía sin tocar la página,
   que sigue igual para quien la abra aparte o llegue desde Google. */
.rec-modal__doc h2 {
  font-size: 1.12rem;
  line-height: 1.3;
  margin: 1.7rem 0 .5rem;
}
.rec-modal__doc h3 {
  font-size: .98rem;
  margin: 1.2rem 0 .4rem;
}
.rec-modal__doc p,
.rec-modal__doc li {
  font-size: .93rem;
  line-height: 1.65;
}
.rec-modal__doc .legal__lead { font-size: .97rem; }
.rec-modal__doc .legal__updated {
  font-size: .78rem;
  margin-bottom: 1.2rem;
}
.rec-modal__title { margin-bottom: .4rem; }

/* Pie del modal de privacidad — 2026-08-26.
   Dos estados en el mismo espacio: mientras no se llegue al final, un
   aviso de qué falta; al llegar, el botón que marca el consentimiento.
   El pie es sticky para que el aviso se vea desde el primer momento y
   no haya que descubrirlo bajando. */
.rec-modal__doc-pie {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.rec-modal__hint {
  margin: 0;
  font-family: var(--font-mono);
  font-size: .74rem;
  letter-spacing: .04em;
  color: var(--gray-text, #6b7280);
}
.rec-modal__aceptar {
  padding: .55rem 1.1rem;
  font-size: .88rem;
  white-space: nowrap;
}
/* La caja recibe foco por JS cuando aún no se ha leído, para que la
   rueda y las flechas funcionen de una. El anillo se oculta porque el
   foco acá es funcional, no una indicación al usuario. */
.rec-modal__box--doc:focus { outline: none; }

/* ════════════════════════════════════════════════════════════
   BANDA DE IMAGEN DE LAS PÁGINAS DE SOLUCIÓN — 2026-08-26
   Va a ancho completo, justo antes del CTA de cierre. Por qué ahí
   y no en el hero: el hero de estas páginas ya carga un diagrama,
   y una foto detrás del titular pelearía con él y con la lectura.
   Después del bloque técnico, en cambio, la página es pura tipografía
   y agradece un respiro antes de pedir la acción.
   La imagen es ilustrativa y el pie lo dice: en este sitio nada
   generado puede leerse como evidencia de un proyecto.
   ════════════════════════════════════════════════════════════ */
.sol-photo {
  position: relative;
  background: #0b0b0d;
}
.sol-photo__fig {
  margin: 0;
  position: relative;
}
.sol-photo__img {
  display: block;
  width: 100%;
  height: clamp(240px, 38vw, 460px);
  object-fit: cover;
  filter: saturate(.9);
}
/* Degradados en los dos bordes: la foto entra y sale del negro del
   sitio en vez de quedar como un recuadro pegado. */
.sol-photo__fig::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(11,11,13,.9) 0%, rgba(11,11,13,0) 22%, rgba(11,11,13,0) 62%, rgba(11,11,13,.92) 100%);
}
.sol-photo__cap {
  position: relative;
  z-index: 1;
  margin: -3.2rem auto 0;
  padding: 0 1.5rem 1.6rem;
  max-width: 1180px;
  font-family: var(--font-mono);
  font-size: .68rem;
  line-height: 1.6;
  letter-spacing: .03em;
  color: rgba(255, 255, 255, .42);
}
@media (max-width: 640px) {
  .sol-photo__cap { margin-top: -2.4rem; font-size: .64rem; }
}

/* El diagrama, ya en el cuerpo: se le pone un ancho máximo para que
   no quede estirado de lado a lado en pantallas grandes. */
.viz-band .hviz {
  max-width: 860px;
  margin: 0 auto;
}

/* ════════════════════════════════════════════════════════════
   EL MOMENTO DE LA IMAGEN — páginas de solución · 2026-08-26
   Tercera versión, y las dos anteriores enseñaron algo:

   1ª  Imagen al final de la página: nadie llegaba a verla.
   2ª  Imagen de fondo del hero al 50 % bajo un velo cargado:
       sobre fondo casi negro quedaba como una sombra. Estaba
       publicada y aun así «no se veía» — que es peor que no
       ponerla, porque pesa y no comunica.

   Esta versión le da a la imagen un momento propio: ancho
   completo, inmediatamente después del titular, con una sola
   frase encima. Y el aclarado va ligado al scroll — entra
   oscura y se abre conforme la persona baja, que es cuando ya
   leyó la promesa y está lista para mirar.

   El progreso lo escribe `script.js` en la variable `--p` (0 a 1).
   SIN JavaScript la imagen queda en su estado abierto, no negra:
   un fallo de script no puede dejar un bloque oscuro sin sentido.
   ════════════════════════════════════════════════════════════ */
.shot {
  position: relative;
  height: clamp(360px, 56vh, 620px);
  overflow: hidden;
  background: #0b0b0d;
  --p: 1;
}
.shot__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(calc(1.09 - (0.09 * var(--p))));
  filter: brightness(calc(0.38 + (0.62 * var(--p)))) saturate(calc(0.72 + (0.28 * var(--p))));
  will-change: transform, filter;
}
/* Velo mínimo y solo abajo: lo justo para que la frase se lea.
   Arriba la imagen queda limpia — es su momento, no el del texto. */
.shot__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(11,11,13,.55) 0%, rgba(11,11,13,0) 26%, rgba(11,11,13,0) 46%, rgba(11,11,13,.88) 100%);
}
.shot__inner {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  width: 100%;
  padding-bottom: 2rem;
}
.shot__line {
  margin: 0;
  max-width: 30ch;
  font-size: clamp(1.15rem, 2vw, 1.6rem);
  line-height: 1.35;
  color: #fff;
  opacity: calc(0.25 + (0.75 * var(--p)));
  transform: translateY(calc(14px - (14px * var(--p))));
}
.shot__note {
  margin: .9rem 0 0;
  font-family: var(--font-mono);
  font-size: .6rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(255,255,255,.3);
}
@media (prefers-reduced-motion: reduce) {
  .shot__img  { transform: none; transition: none; }
  .shot__line { transform: none; }
}

/* Tira de marcas en par — 2026-08-26.
   Cuando la página representa a dos marcas que se complementan, la
   retícula se centra en vez de repartir cuatro columnas: dos logos
   estirados de lado a lado se leen como un muro incompleto. */
/* La tira mide según cuántas marcas haya — 2026-08-26.
   `--par` fijaba dos pistas de 220px y centraba el contenido, pero el
   contenedor seguía siendo ancho: como la retícula aporta el fondo gris
   de las líneas (bloque 8), ese gris quedaba asomando a los dos lados
   de los logos. Se veía como dos celdas vacías. Con `width: max-content`
   la caja gris termina donde terminan los logos, y sirve igual para dos
   marcas que para seis: no hay que tocar nada al agregar una. */
.brands-grid--strip {
  width: max-content;
  max-width: 100%;
  margin-inline: auto;
  grid-template-columns: repeat(auto-fit, minmax(180px, 220px));
}
@media (max-width: 539px) {
  .brands-grid--strip { width: auto; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.brands-strip__line {
  max-width: 68ch;
  margin: 1.25rem auto 0;
  text-align: center;
  font-size: .95rem;
  line-height: 1.7;
}

/* ════════════════════════════════════════════════════════════
   BANDA DEL DIAGRAMA — corrección 2026-08-26
   Al bajar el diagrama del hero al cuerpo quedó sobre fondo claro,
   y todas las clases `.hviz__*` están construidas para fondo
   oscuro: texto blanco al 34 %, bordes al 8 %. Sobre gris claro
   eso desaparece — el diagrama estaba ahí y no se leía.

   La banda recupera el fondo oscuro en el que el diagrama fue
   dibujado, en vez de reescribir treinta reglas de color.
   ⚠️ No cambiar `.viz-band` a un fondo claro sin antes revisar
   el bloque 20 de este archivo: se rompe el mismo día.
   ════════════════════════════════════════════════════════════ */
.viz-band {
  background: #0b0b0d;
  padding: var(--section-py) 0;
}
.viz-band .hviz {
  max-width: 860px;
  margin: 0 auto;
}


/* ════════════════════════════════════════════════════════════
   21 · HERO ÚNICO CON FOTO — 2026-08-26
   ════════════════════════════════════════════════════════════
   Antes había DOS bloques a pantalla completa uno detrás del
   otro: `.page-hero` (charcoal, migaja + h1 + bajada) y `.shot`
   (la foto con su frase). Dos heros seguidos para una sola
   página. Se funden en uno.

   Qué se conserva y qué no, y por qué:
   · El `<h1>` grande NO se toca. Es el titular de siempre y el
     que dice qué se vende.
   · La frase de `.shot__line` pasa a `.page-hero__line`, debajo
     del titular. Acompaña, no reemplaza.
   · La bajada larga SALE del hero. Tres bloques de texto sobre
     una foto es un muro; además en casi todas las páginas ese
     mismo párrafo ya está repetido en el `.section-header` de
     la primera banda. Donde no lo estaba, se bajó al cuerpo.

   El aclarado al bajar lo maneja el módulo de script.js con
   `data-shot="hero"`: aquí el avance lo marca cuánto ha subido
   el hero, no cuánto ha entrado — un hero está en pantalla
   desde el primer cuadro y con la fórmula de los bloques
   normales nacería ya aclarado y no se vería nunca el efecto.

   ⚠️ `--p` arranca en 1, no en 0. Si el script no corre la foto
   se queda ABIERTA. Un fallo no puede dejar un rectángulo negro.
   ════════════════════════════════════════════════════════════ */
.page-hero--shot {
  --p: 1;
  padding: 0;
  /* El tope de 700px es para pantallas normales. En una ventana de
     2560 ese alto deja el hero en 3,66:1 y, como la foto es 16:9,
     `object-fit: cover` se come casi la mitad del alto de la imagen y
     recorta al sujeto — el radomo de sincronía y el tanque de
     telemetría quedaban partidos. Arriba de 1500px el alto pasa a
     seguir al ancho (34vw) y la proporción se estabiliza en ~2,9:1,
     que es donde las nueve fotos aguantan el recorte. Comprobado
     recortando las nueve a esa proporción antes de fijar el número. */
  min-height: clamp(500px, 74vh, 700px);
  display: flex;
  align-items: flex-end;
  background: #0b0b0d;
}
.page-hero__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(calc(1.06 - (0.06 * var(--p))));
  /* El piso de brillo es 0,66 y no 0,44 como en el `.shot` viejo. La
     diferencia importa: el `.shot` era un bloque de paso que entraba
     oscuro y se abría al bajar, y podía permitirse arrancar casi
     negro. Este es el hero — lo primero que ve alguien que llega, y
     dos de las fotos (la de IA privada y la de respaldo) ya son
     oscuras de origen. Con 0,44 encima no se veía nada, que es
     exactamente el reclamo del 26/08. */
  filter: brightness(calc(0.66 + (0.34 * var(--p)))) saturate(calc(0.82 + (0.18 * var(--p))));
  will-change: transform, filter;
}
/* El velo carga abajo, donde va el texto, y deja el tercio alto
   casi limpio: ahí la foto es la foto. No es un velo plano
   porque un velo plano apaga la imagen entera para resolver un
   problema que solo existe detrás de las letras. */
.page-hero__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom,
    rgba(11,11,13,.62) 0%,
    rgba(11,11,13,.20) 26%,
    rgba(11,11,13,.34) 52%,
    rgba(11,11,13,.94) 100%);
}
.page-hero--shot .page-hero__text {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-top: 152px;
  padding-bottom: 52px;
}
.page-hero--shot h1 { margin-bottom: 20px; }
.page-hero__line {
  margin: 0;
  max-width: 36ch;
  font-size: clamp(1.08rem, 1.9vw, 1.42rem);
  font-weight: 300;
  line-height: 1.45;
  letter-spacing: -0.01em;
  color: rgba(255,255,255,.86);
  opacity: calc(0.42 + (0.58 * var(--p)));
  transform: translateY(calc(10px - (10px * var(--p))));
}
.page-hero__note {
  position: absolute;
  right: 26px;
  bottom: 14px;
  z-index: 2;
  margin: 0;
  font-family: var(--font-mono);
  font-size: .58rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(255,255,255,.3);
}
@media (min-width: 1500px) {
  .page-hero--shot { min-height: min(78vh, 34vw); }
}
@media (max-width: 640px) {
  .page-hero--shot { min-height: 460px; }
  .page-hero--shot .page-hero__text { padding-top: 120px; padding-bottom: 40px; }
}
@media (prefers-reduced-motion: reduce) {
  .page-hero__img  { transform: none; }
  .page-hero__line { transform: none; opacity: 1; }
}


/* ════════════════════════════════════════════════════════════
   22 · TEXTO EN DOS COLUMNAS CON APOYO AL LADO — 2026-08-26
   ════════════════════════════════════════════════════════════
   El reclamo: los bloques de prosa ocupaban la mitad izquierda
   de la pantalla y dejaban toda la columna derecha vacía.

   La salida NO fue alargar la línea. `.sol-lead` mide 68ch, que
   ya está en el techo de lo que se lee cómodo —de 75 en adelante
   el ojo pierde el renglón al volver—, así que ensanchar habría
   arreglado el hueco empeorando la lectura. Lo que sobraba no era
   medida: era una columna sin nada.

   Así que ahí va el apoyo visual. El diagrama que hasta hoy tenía
   banda propia al final de la página —540px de dibujo en una
   franja de 1180— se sube al lado del texto que explica lo mismo.
   Un movimiento, dos problemas.

   El diagrama viaja con su fondo oscuro puesto (`.sol-aside__card`).
   Todas las clases `.hviz__*` están dibujadas en blanco al 34%: sin
   ese fondo desaparecen sobre el gris claro, que es exactamente lo
   que pasó el 26/08 cuando se sacaron de los heros.
   ⚠️ No poner un `.hviz` fuera de un contenedor oscuro.
   ════════════════════════════════════════════════════════════ */
.sol-split { display: block; }
@media (min-width: 1024px) {
  .sol-split {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    gap: 60px;
    align-items: start;
  }
}
/* Dentro de la columna el tope de 68ch ya no manda —la pista es más
   angosta que eso— pero se deja para que el bloque no dependa del
   ancho de la retícula si alguien la cambia. */
.sol-split__text > .sol-lead,
.sol-split__text > .sol-points,
.sol-split__text > .sol-scope { max-width: 68ch; }

.sol-split__aside { align-self: start; }
@media (min-width: 1024px) {
  .sol-split__aside { position: sticky; top: 96px; }
}
@media (max-width: 1023px) {
  .sol-split__aside { margin-top: 40px; }
}
.sol-aside__card {
  background: #0b0b0d;
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 2px;
  padding: 18px;
}
.sol-aside__card .hviz {
  background: none;
  border: 0;
}
.sol-aside__card .hviz__svg { width: 100%; height: auto; display: block; }
.sol-aside__note {
  margin: 12px 0 0;
  font-family: var(--font-mono);
  font-size: .6rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(255,255,255,.32);
}

/* Secciones de prosa que NO tienen apoyo al lado: en vez de dejar
   el hueco a la derecha se centra la columna entera —cabecera
   incluida, si no el desalineado se lee como un error— y el aire
   queda repartido a los dos lados, que es aire y no un vacío. */
.container--prosa { max-width: 900px; }

/* Al bajar de una banda de 1180px a una columna de ~480px el dibujo
   pierde cerca de un 15% de escala y los rótulos quedan a ~7px
   efectivos. A ese tamaño el blanco al 34% deja de leerse — es el
   mismo problema de contraste de esta mañana, solo que por tamaño en
   vez de por fondo. Dentro de la tarjeta se suben las opacidades más
   bajas; fuera de ella no se toca nada. */
.sol-aside__card .hviz__cap--soft { fill: rgba(255, 255, 255, .56); }
.sol-aside__card .hviz__note      { color: rgba(255, 255, 255, .48); }
.sol-aside__card .hviz__line--blind { stroke: rgba(255, 255, 255, .28); }


/* ════════════════════════════════════════════════════════════
   23 · EL NAV DICE EN QUÉ SOLUCIÓN ESTÁS — 2026-08-26
   ════════════════════════════════════════════════════════════
   «Cuando bajo en la página a veces no me acuerdo en cuál
   estoy». El dato ya existía —`aria-current="page"` está en las
   diez páginas desde que se creó el desplegable— pero solo lo
   oía un lector de pantalla. Aquí se hace visible en dos
   lugares: el botón de la barra y la entrada del desplegable.

   El nombre corto lo pone script.js (bloque 15) leyendo el
   `data-corto` del enlace marcado. En móvil se oculta: ahí el
   menú es una columna y el ítem actual ya se ve solo.
   ════════════════════════════════════════════════════════════ */
.nav__dd-btn__ahora {
  display: inline-flex;
  align-items: center;
  max-width: 15ch;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .04em;
  color: var(--orange);
}
/* La barrita separadora es un borde y no un carácter: un «·» en el
   texto se lo lee el lector de pantalla en medio del nombre. */
.nav__dd-btn__ahora::before {
  content: '';
  width: 1px;
  height: 11px;
  margin: 0 9px 0 3px;
  background: rgba(255,255,255,.28);
}
@media (max-width: 1199px) {
  .nav__dd-btn__ahora { display: none; }
}

/* La entrada abierta, dentro del desplegable */
.nav__dd-link[aria-current="page"] {
  color: var(--orange);
  background: rgba(223,106,46,.07);
}
.nav__dd-link[aria-current="page"] .nav__dd-num { color: var(--orange); opacity: .8; }


/* ════════════════════════════════════════════════════════════
   24 · MINIATURAS DE LA LISTA DE SOLUCIONES — 2026-08-26
   ════════════════════════════════════════════════════════════
   Las nueve fotos de los heros, en chico, dentro del índice de
   la portada. La decisión de fondo está anotada en el HTML: no
   van arriba, van aquí, donde la imagen hace un trabajo —decir
   a qué página lleva la fila— en vez de solo ambientar.

   Debajo de 960px la miniatura NO se muestra. En una columna la
   foto se pone entre el número y el texto y parte la fila en
   dos; y en móvil son nueve descargas para adornar una lista
   que ahí se lee perfecto sin ellas. Por eso `loading="lazy"`
   además: el índice está bien abajo de la portada.
   ════════════════════════════════════════════════════════════ */
.spec-row__shot { display: none; }
@media (min-width: 960px) {
  .spec-row__shot {
    display: block;
    position: relative;
    overflow: hidden;
    border-radius: 2px;
    background: #0b0b0d;
    aspect-ratio: 3 / 2;
    align-self: start;
    margin-top: 4px;
  }
  .spec-row__shot img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    /* Cuatro de las nueve fotos son escenas nocturnas o de cuarto de
       equipos a oscuras. A 168px de ancho, con un filtro de .82 encima,
       dejaban de leerse como algo y pasaban a ser rectángulos oscuros.
       El reposo queda casi limpio y el hover solo abre el último tramo. */
    filter: brightness(.94) saturate(.92);
    transform: scale(1.02);
    transition: filter var(--transition), transform var(--transition);
  }
  /* La fila entera ya se aclara al pasar el mouse (`.spec-row:hover`);
     la foto acompaña ese gesto en vez de tener uno propio. */
  .spec-row:hover .spec-row__shot img {
    filter: brightness(1) saturate(1);
    transform: scale(1.06);
  }
}
@media (prefers-reduced-motion: reduce) {
  .spec-row__shot img,
  .spec-row:hover .spec-row__shot img { transform: none; transition: none; }
}

/* Reemplaza al `width="100%" height="auto"` que traía el SVG de la línea
   de tiempo de respaldo. `height="auto"` no es un valor válido de atributo
   SVG y el navegador lo descartaba con un error de consola. */
.hviz__svg--fluido { width: 100%; height: auto; display: block; }

/* Un párrafo pegado a una lista de puntos se leía como el último punto
   sin viñeta. Existía `.sol-lead + .sol-lead` pero no este par, y hasta
   ahora no se había dado la combinación en ninguna página. */
.sol-points + .sol-lead,
.sol-points + .sol-scope { margin-top: 26px; }


/* ════════════════════════════════════════════════════════════
   25 · PANTALLAS GRANDES — 2026-08-26
   ════════════════════════════════════════════════════════════
   Julián: «está DEMASIADO pequeño», sobre la barra de arriba.
   Medí su ventana antes de tocar nada: **2560 px de ancho**.

   La barra no está chica. El sitio no crece. Hasta hoy el
   archivo no tenía UNA sola regla por encima de 1400px: de ahí
   en adelante el contenedor se quedaba clavado en 1180px y la
   tipografía en 16px, así que en un monitor de 2560 el
   contenido ocupaba el 46 % del ancho y todo se leía a la
   mitad del tamaño aparente. En un portátil de 1440 —donde se
   diseñó— se ve bien, y por eso nunca salió.

   Se arregla en la raíz y no pieza por pieza: subir
   `font-size` del `html` reescala todo lo que está en `rem`,
   que es casi todo el archivo, y `--container` acompaña para
   que la línea de texto no se estire de más. Tocar solo el nav
   habría dejado el resto igual de chico.

   Los titulares usan `clamp()` con `vw`, así que ya crecían
   solos; por eso los titulares se veían bien y la barra no.
   ════════════════════════════════════════════════════════════ */
@media (min-width: 1700px) {
  html { font-size: 17px; }
  :root { --container: 1300px; }
  .nav__inner { height: 88px; }
  .nav__logo img { height: 56px; }
}
@media (min-width: 2100px) {
  html { font-size: 18.5px; }
  :root { --container: 1440px; }
  .nav__inner { height: 96px; }
  .nav__logo img { height: 64px; }
}

/* ── Nombres de marca clicables dentro del párrafo ──────────────
   Antes eran `<strong>` y al final del texto había un «Ver las
   fichas técnicas» que mandaba a la portada. Ahora el nombre
   mismo abre la ficha, en la misma página. Se le deja un
   subrayado punteado porque un `<button>` que parece texto
   corrido nadie lo toca: la afordancia tiene que verse. */
.brand-inline {
  font: inherit;
  font-weight: 600;
  color: var(--orange-text);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  border-bottom: 1px dotted currentColor;
  transition: color var(--transition), border-color var(--transition);
}
.brand-inline:hover { border-bottom-style: solid; }
.brand-inline:focus-visible { outline: 2px solid var(--orange); outline-offset: 3px; }


/* ════════════════════════════════════════════════════════════
   26 · PROSA CENTRADA CON FIGURA A LO ANCHO — 2026-08-26
   ════════════════════════════════════════════════════════════
   Reemplaza al bloque 22 (`.sol-split`), que duró unas horas.

   Aquel intento ponía el diagrama en una columna a la derecha
   del texto para tapar el hueco. Tapaba el hueco y creaba dos
   problemas: el dibujo mide 540×230 —es rectangular por
   naturaleza— y en una pista de 480px se encogía hasta dejar
   los rótulos a 7px, ilegibles; y la fila entera se leía como
   si algo no cupiera.

   Lo que hay ahora es lo que pidió Julián y es además lo
   correcto: el texto a una medida cómoda y CENTRADO —el aire
   repartido a los dos lados, no todo a la derecha— y la figura
   a lo ancho, entre párrafos, con su forma rectangular
   intacta. El dibujo vuelve a su tamaño real y de paso parte
   la lectura, que es lo que hace una figura en un texto largo.

   `.sol-flujo` centra la cabecera y la prosa; lo que NO es
   prosa —retículas, figuras, la nota final— se queda a lo
   ancho del contenedor.
   ════════════════════════════════════════════════════════════ */
.sol-flujo > .section-header,
.sol-flujo > .sol-lead,
.sol-flujo > .sol-points,
.sol-flujo > .sol-scope,
.sol-flujo > .sdemo__kicker {
  max-width: 720px;
  margin-inline: auto;
}
/* `.section-header` trae su propio tope de 680px del bloque base y
   ganaría por especificidad de orden; se iguala para que el texto y la
   cabecera arranquen en la misma vertical. Un renglón desalineado con
   otro por 40px no se lee como estilo, se lee como error. */
.sol-flujo > .section-header { max-width: 720px; }

.sol-figura {
  margin: 46px 0;
}
/* Tope de 940px, ni 480 ni los 1132 del contenedor. Es un número medido,
   no un gusto: el dibujo está trazado a 540px de ancho, así que a 1132
   se estira a 2,1× y los rótulos de 9px salen a 19 — el diagrama grita.
   A 940 la escala queda en 1,6× y los rótulos rondan los 14px, que es
   donde se leen sin dominar la página. Y centrado, igual que la prosa:
   las dos columnas comparten eje y el aire queda repartido. */
.sol-figura__card {
  max-width: 940px;
  margin-inline: auto;
  background: #0b0b0d;
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 2px;
  padding: 22px 24px;
}
.sol-figura__card .hviz {
  background: none;
  border: 0;
  max-width: none;
}
.sol-figura__card .hviz__svg { width: 100%; height: auto; display: block; }
@media (max-width: 700px) {
  .sol-figura { margin: 34px 0; }
  .sol-figura__card { padding: 14px 14px; }
}

/* Tres CTA dejaron de ser `<a href="index.html#marcas">` para volverse
   `<button data-brand>` que abre la ficha en la propia página. Un
   `<button>` arrastra estilos del navegador que un `<a>` no tiene
   —tipografía del sistema, borde 3D, cursor de flecha— y sin esto los
   tres botones se veían distintos a los demás sin que nadie entendiera
   por qué. NO se toca `background` ni `border` aquí: los declara cada
   variante (`.btn--primary`, `.btn--outline`) más arriba, y ponerlos en
   esta regla los anularía por orden de cascada. */
button.btn {
  font-family: inherit;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

/* ── Retrato junto al formulario — 2026-08-26 ───────────────────
   Primero fue una banda a lo ancho con la foto del equipo; quedó
   como un encabezado y competía con el titular. Un retrato chico
   al lado de una línea de texto hace el mismo trabajo —decir que
   hay alguien del otro lado— sin pelearle el primer plano a
   «Hablemos de su proyecto». */
.form-atiende {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 30px;
}
.form-atiende__foto {
  width: 76px;
  height: 76px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(255,255,255,.14);
}
.form-atiende__texto {
  margin: 0;
  /* 28ch y no 24: la frase pasó a «…integra las soluciones para su
     organización» el 26/08 y a 24 caracteres partía en cuatro renglones
     al lado de un retrato de 76px — la columna de texto quedaba más
     alta que la foto y el bloque se veía desbalanceado. */
  max-width: 28ch;
  font-size: 1rem;
  line-height: 1.45;
  color: rgba(255,255,255,.72);
}
@media (min-width: 1700px) {
  .form-atiende__foto { width: 88px; height: 88px; }
}

/* ── El muro de clientes, más grande — 2026-08-26 ────────────────
   «El que está debajo del TSE de fijo hay que hacerlo más grande,
   no se lee nada»: es el lockup del Centro Nacional de la Música,
   `client-logo--wide`. Su archivo mide 160×23, o sea casi 7:1, y en
   una celda de cuarto de fila el ancho —no el alto— era lo que lo
   ahogaba: subirle el `max-height` no servía de nada porque nunca
   llegaba a ese tope. Por eso ocupa DOS columnas.

   De paso las celdas crecen un punto: 96px de alto era la medida de
   cuando el muro era una tira de relleno, y hoy es la prueba más
   fuerte de la portada. */
.client-cell { min-height: 112px; padding: 22px 18px; }
.client-cell img { max-height: 46px; }
.client-cell img.client-logo--seal { max-height: 60px; }
.client-cell img.client-logo--boxy { max-height: 50px; }

@media (min-width: 540px) {
  .client-cell:has(.client-logo--wide) { grid-column: span 2; }
}
.client-cell img.client-logo--wide { max-height: 40px; }

@media (min-width: 1700px) {
  .client-cell { min-height: 128px; }
  .client-cell img { max-height: 52px; }
  .client-cell img.client-logo--seal { max-height: 66px; }
  .client-cell img.client-logo--boxy { max-height: 56px; }
  .client-cell img.client-logo--wide { max-height: 46px; }
}

/* ════════════════════════════════════════════════════════════
   27 · FOTOS DE FONDO EN EL HERO ROTATIVO — 2026-08-28
   ════════════════════════════════════════════════════════════
   Hasta hoy la portada tenía fondo negro con un diagrama SVG a la
   derecha de cada pantalla, mientras las páginas de solución ya
   habían pasado a foto a lo ancho con el texto encima. Las dos
   cosas no se parecían, y la portada es la primera que se ve.

   Se traen las mismas cuatro fotos que usan las internas —una por
   pantalla— y el diagrama sale. No se pierde: las topologías siguen
   vivas dentro de cada página de solución, que es donde alguien las
   mira con calma. En un carrusel que rota cada siete segundos nadie
   llegaba a leerlas.

   POR QUÉ LAS FOTOS VAN FUERA DE .container
   Tienen que sangrar a todo el ancho de la pantalla. Adentro del
   contenedor quedarían con los márgenes laterales, que en pantallas
   grandes son 200px o más de negro a cada lado.

   POR QUÉ NO VAN DENTRO DE CADA .hero__slide
   Las diapositivas viven en una rejilla de una sola celda y se cruzan
   por opacidad. Si la foto fuera hija de la diapositiva heredaría esa
   opacidad y además quedaría recortada al ancho del contenedor. Van
   en su propia capa y se sincronizan desde el mismo `pintar()` que ya
   mueve las diapositivas y los puntos — una línea más, no un
   temporizador aparte que se pueda desfasar.
   ════════════════════════════════════════════════════════════ */

.hero__shots {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}

.hero__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 42%;
  opacity: 0;
  /* Mismo brillo y saturación que el hero de las internas ya asentado
     (bloque 21). Sin esto el texto blanco se pierde sobre los claros
     de la foto. */
  filter: brightness(.74) saturate(.86);
  transition: opacity .55s var(--ease);
}
.hero__shot.is-active { opacity: 1; }

/* Dos velos superpuestos, y son dos problemas distintos.

   El HORIZONTAL es el que hace el trabajo de verdad: el texto vive en
   la mitad izquierda, así que ahí se oscurece fuerte y hacia la derecha
   se abre para que la foto se vea. Un velo parejo no servía — o tapaba
   la foto entera o dejaba el texto ilegible; no hay punto medio cuando
   se aplica igual en toda la superficie.

   El VERTICAL solo cierra el pie, porque ahí van las cifras (88 · 1999
   · 600+ · 11 · 25+), que son texto chico y no perdonan fondo con
   detalle. */
.hero__veil {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(to bottom,
      rgba(11,11,13,.40) 0%,
      rgba(11,11,13,.10) 34%,
      rgba(11,11,13,.30) 66%,
      rgba(11,11,13,.92) 100%),
    linear-gradient(to right,
      rgba(11,11,13,.86) 0%,
      rgba(11,11,13,.72) 38%,
      rgba(11,11,13,.28) 68%,
      rgba(11,11,13,.10) 100%);
}
@media (max-width: 900px) {
  /* En vertical el texto ocupa todo el ancho, así que el degradado
     lateral deja de tener sentido y se vuelve parejo. */
  .hero__veil {
    background: linear-gradient(to bottom,
      rgba(11,11,13,.72) 0%,
      rgba(11,11,13,.60) 40%,
      rgba(11,11,13,.70) 70%,
      rgba(11,11,13,.94) 100%);
  }
}

/* El contenido por encima de foto y velo. */
.hero > .container { position: relative; z-index: 2; }

/* El diagrama sale de la portada. Se oculta en vez de borrarlo del
   HTML: sigue siendo el mismo marcado que las internas comparten, y
   si algún día se quiere volver atrás es una línea. */
.hero__topology { display: none; }

/* Con el diagrama fuera, la rejilla de dos columnas ya no aplica: el
   texto se queda en su ancho de lectura y la foto ocupa el resto.
   Se anula también la variante de 980px del bloque original. */
.hero__layout { grid-template-columns: 1fr; }
@media (min-width: 980px) {
  .hero__layout { grid-template-columns: 1fr; }
}

/* El resplandor naranja del fondo original competía con la foto y
   ensuciaba los medios tonos. Con imagen detrás ya no hace falta. */
.hero::before { display: none; }

@media (prefers-reduced-motion: reduce) {
  .hero__shot { transition: none; }
}
