/* =====================================================================
   Plataforma Comercial Ventus — hoja de estilo

   Replica la estructura de Salesforce Lightning con la identidad de
   Ventus. Las medidas no son aproximadas: salen de leer el Lightning
   Design System 2.25.6 y quedan anotadas donde se usan.

     barra global      3.125rem   (.slds-global-header)
     barra de módulos  2.5rem     (.slds-context-bar), con regla inferior
                                  de 3px en el color de la aplicación
     pestaña activa    barra de 3px arriba + fondo al 10% de ese color
     ruta de etapas    eslabón de 2rem, punta de flecha con dos
                       pseudo-elementos sesgados 28° y -30°

   Sin dependencias externas ni paso de compilación: tipografías del
   sistema, iconos en SVG en línea. La aplicación se ve igual sin red.

   ---------------------------------------------------------------------
   REGLA DE COLOR

   El verde Ventus es identidad, no es un semáforo. Se reserva para el
   armazón —barra, pestaña activa, botones primarios, enlaces, series de
   gráfico— y NUNCA para decir que un dato está bien.

   Lo que significa "correcto" usa el verde claro del kit llevado a oliva
   (#87BB59 → #4F7A24): 71° de separación de tono contra el verde de
   marca, así que un distintivo de "licencia otorgada" no se lee como
   "esto es de Ventus". Alerta y error salen del naranja y el rojo del
   kit, oscurecidos hasta pasar 4,5:1 sobre blanco.
   ===================================================================== */

:root {

  /* ---- Kit de marca Ventus, sin retocar ---- */
  --ventus-verde:        #008F5F;   /* principal */
  --ventus-verde-claro:  #87BB59;
  --ventus-gris:         #737373;
  --ventus-naranja:      #DF8834;
  --ventus-azul-claro:   #0097C2;
  --ventus-azul-oscuro:  #04708E;
  --ventus-amarillo:     #FFE681;
  --ventus-rojo:         #FF756A;

  /* ---- Marca aplicada ----
     --marca es el hex del kit y va en superficies, reglas, barras y
     rellenos. --marca-osc es el mismo verde oscurecido, para fondos que
     cargan texto blanco pequeño (blanco sobre #008F5F da 4,12:1, corto
     para AA; sobre #00734C da 5,90:1) y para texto verde sobre blanco. */
  --marca:        #008F5F;
  --marca-osc:    #00734C;
  --marca-prof:   #005538;
  --barra-fondo:  #00734C;   /* fondo de la barra global; blanco encima = 5,90:1 */
  --marca-04:     rgba(0, 143, 95, .05);
  --marca-10:     rgba(0, 143, 95, .10);
  --marca-16:     rgba(0, 143, 95, .16);
  --marca-30:     rgba(0, 143, 95, .30);

  /* ---- Semánticos: deliberadamente fuera del verde de marca ---- */
  --exito:         #4F7A24;               /* oliva, del verde claro */
  --exito-fondo:   #F1F7E9;
  --exito-borde:   #C3DDA0;
  --alerta:        #A85A08;               /* del naranja */
  --alerta-fondo:  #FDF3E6;
  --alerta-borde:  #F0C58C;
  --critico:       #B32D24;               /* del rojo */
  --critico-fondo: #FDEEED;
  --critico-borde: #F5B3AD;
  --info:          #04708E;               /* azul oscuro */
  --info-fondo:    #E9F5F9;
  --info-borde:    #9CD2E4;
  --neutro:        #5C5C5C;
  --neutro-fondo:  #F0F0F0;
  --neutro-borde:  #D8D8D8;

  /* ---- Neutros ---- */
  --fondo:        #F3F3F3;
  --panel:        #FFFFFF;
  --panel-2:      #FAFAF9;
  --panel-3:      #F0F1F2;
  --linea:        #E5E5E5;
  --linea-fuerte: #C9C9C9;
  --texto:        #181818;
  --texto-2:      #444444;
  --texto-3:      #5C5C5C;

  /* ---- Métrica ---- */
  --alto-barra:   3.125rem;   /* .slds-global-header */
  --alto-nav:     2.5rem;     /* .slds-context-bar   */
  --radio:        .25rem;
  --radio-g:      .5rem;
  --sombra-1:     0 2px 2px 0 rgba(0, 0, 0, .10);
  --sombra-2:     0 2px 4px rgba(0, 0, 0, .07);
  --sombra-3:     0 8px 24px rgba(0, 0, 0, .16), 0 2px 6px rgba(0, 0, 0, .10);

  --fuente: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --marca:        #2FB98A;
    --marca-osc:    #23A97B;
    --marca-prof:   #7EDCBB;
    /* En oscuro el verde aclarado sirve para texto sobre panel, pero como
       fondo de barra dejaría el blanco en 2,99:1. La barra se va al verde
       profundo: blanco encima = 8,04:1. */
    --barra-fondo:  #0A5C3E;
    --marca-04:     rgba(47, 185, 138, .06);
    --marca-10:     rgba(47, 185, 138, .14);
    --marca-16:     rgba(47, 185, 138, .22);
    --marca-30:     rgba(47, 185, 138, .38);

    --exito:         #A9CE72;
    --exito-fondo:   #23301A;
    --exito-borde:   #486B23;
    --alerta:        #E6A45C;
    --alerta-fondo:  #33230F;
    --alerta-borde:  #7A5215;
    --critico:       #FF9187;
    --critico-fondo: #351A18;
    --critico-borde: #7E332C;
    --info:          #5FC3E0;
    --info-fondo:    #102B34;
    --info-borde:    #1E5C72;
    --neutro:        #A8A8A8;
    --neutro-fondo:  #232527;
    --neutro-borde:  #3A3D40;

    --fondo:        #101214;
    --panel:        #191C1E;
    --panel-2:      #1E2224;
    --panel-3:      #24282B;
    --linea:        #2C3134;
    --linea-fuerte: #3D4347;
    --texto:        #ECEFF1;
    --texto-2:      #B4BCC0;
    --texto-3:      #8D9599;
    --sombra-1:     0 2px 2px 0 rgba(0, 0, 0, .40);
    --sombra-2:     0 2px 4px rgba(0, 0, 0, .35);
    --sombra-3:     0 8px 24px rgba(0, 0, 0, .55), 0 2px 6px rgba(0, 0, 0, .40);
  }
}

/* =====================================================================
   Base
   ===================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

/* El armazón ocupa exactamente la ventana y no desplaza: lo que desplaza es
   el lienzo. Así una lista o un tablero llenan la pantalla en un monitor de
   27" en vez de dejar la mitad de abajo en blanco, y las barras superiores
   no necesitan `position: fixed` ni que el contenido reserve su alto. */
body {
  margin: 0;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--fondo);
  color: var(--texto);
  font-family: var(--fuente);
  font-size: 13px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

button, input, select, textarea { font: inherit; color: inherit; }
a { color: var(--marca-osc); text-decoration: none; }
a:hover { text-decoration: underline; }
[hidden] { display: none !important; }

.solo-lectores {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; border-radius: 2px; }
.barra-global :focus-visible { outline-color: #fff; }

.icono { width: 1rem; height: 1rem; flex: none; fill: currentColor; }
.icono-g { width: 1.25rem; height: 1.25rem; }
.num   { text-align: right; font-variant-numeric: tabular-nums; }
.trunca { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* =====================================================================
   1. Barra global  ·  .slds-global-header — 3.125rem
   En un org de Salesforce con marca propia esta barra toma el color de
   la compañía. Aquí toma el verde Ventus.
   ===================================================================== */

.barra-global {
  position: relative;
  z-index: 100;
  flex: none;
  height: var(--alto-barra);
  display: flex;
  align-items: center;
  gap: .25rem;
  padding: 0 .75rem;
  background: var(--barra-fondo);
  box-shadow: var(--sombra-2);
  color: #fff;
}

/* Lanzador de aplicaciones: la cuadrícula de nueve puntos */
.lanzador {
  display: grid;
  grid-template-columns: repeat(3, 3px);
  grid-auto-rows: 3px;
  gap: 3px;
  padding: .5rem;
  border: 0;
  border-radius: var(--radio);
  background: transparent;
  cursor: pointer;
}
.lanzador span { width: 3px; height: 3px; border-radius: 50%; background: #fff; opacity: .85; }
.lanzador:hover { background: rgba(255,255,255,.16); }
.lanzador:hover span { opacity: 1; }

.logotipo {
  display: flex;
  align-items: baseline;
  gap: .4rem;
  padding: 0 .75rem 0 .5rem;
  margin-right: .25rem;
  white-space: nowrap;
}
.logotipo b { font-size: 15px; font-weight: 700; letter-spacing: -.015em; }
.logotipo i {
  font-style: normal; font-size: 10px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: rgba(255,255,255,.75);
}

/* Buscador global — .slds-global-header__item_search: flex 0 1 33.5rem */
.buscador {
  position: relative;
  flex: 0 1 33.5rem;
  min-width: 8rem;
  margin: 0 auto;
}
.buscador > .icono {
  position: absolute; left: .75rem; top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  fill: var(--texto-3);
}
.buscador input {
  width: 100%;
  height: 2rem;
  padding: 0 .75rem 0 2.25rem;
  border: 1px solid transparent;
  border-radius: var(--radio);
  background: #fff;
  color: #181818;
}
.buscador input::placeholder { color: #5C5C5C; }
.buscador input:focus { outline: 0; border-color: #fff; box-shadow: 0 0 0 3px rgba(255,255,255,.45); }

.buscador-menu {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0;
  max-height: 26rem; overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra-3);
  color: var(--texto);
  padding: .25rem 0;
}
.buscador-menu h4 {
  margin: 0; padding: .5rem .75rem .25rem;
  font-size: 10.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--texto-3);
}
.buscador-menu button {
  display: flex; align-items: center; gap: .5rem;
  width: 100%; padding: .4rem .75rem; border: 0;
  background: none; text-align: left; cursor: pointer;
}
.buscador-menu button:hover, .buscador-menu button:focus-visible { background: var(--marca-10); }
.buscador-menu .nom { flex: 1; min-width: 0; }
.buscador-menu .det { color: var(--texto-3); font-size: 12px; white-space: nowrap; }
.buscador-menu .nada { padding: .75rem; color: var(--texto-3); }

.acciones-globales { display: flex; align-items: center; gap: .125rem; margin-left: auto; }
.acciones-globales button {
  display: grid; place-items: center;
  width: 2rem; height: 2rem;
  border: 0; border-radius: 50%;
  background: transparent; color: #fff;
  cursor: pointer;
}
.acciones-globales button:hover { background: rgba(255,255,255,.16); }
.avatar {
  display: grid; place-items: center;
  width: 2rem; height: 2rem; margin-left: .375rem;
  border: 0; border-radius: 50%;
  background: var(--ventus-verde-claro);
  color: #26430F;
  font-size: 11.5px; font-weight: 700;
  cursor: pointer;
}
.avatar:hover { box-shadow: 0 0 0 2px rgba(255,255,255,.6); }

/* =====================================================================
   2. Barra de módulos  ·  .slds-context-bar — 2.5rem
   Regla inferior de 3px en el color de la aplicación; la pestaña activa
   lleva una barra de 3px arriba y fondo al 10% de ese color.
   ===================================================================== */

.barra-modulos {
  position: relative;
  z-index: 99;
  flex: none;
  display: flex;
  align-items: stretch;
  height: var(--alto-nav);
  padding-left: 1.25rem;
  background: var(--panel);
  border-bottom: 3px solid var(--marca);
}
.nombre-app {
  display: flex; align-items: center; gap: .5rem;
  padding-right: 1rem; margin-right: .5rem;
  border-right: 1px solid var(--linea);
  font-size: 13.5px; font-weight: 700;
  white-space: nowrap;
}
.nombre-app .punto-marca {
  width: .5rem; height: .5rem; border-radius: 2px;
  background: var(--marca);
}

.modulos { display: flex; align-items: stretch; overflow-x: auto; scrollbar-width: none; }
.modulos::-webkit-scrollbar { display: none; }

.modulo {
  position: relative;
  display: flex; align-items: center; gap: .375rem;
  max-width: 15rem;
  padding: 0 .75rem;
  border: 0; border-radius: 0;
  background: transparent;
  color: var(--texto);
  font-size: 13px;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .2s;
}
.modulo:hover { background: var(--marca-10); }
.modulo[aria-selected="true"] { background: var(--marca-10); font-weight: 600; }
.modulo[aria-selected="true"]::before {
  content: ""; position: absolute; top: 0; left: -1px; right: -1px;
  height: 3px; background: var(--marca);
}
.modulo .flecha { width: .625rem; height: .625rem; opacity: .5; }

/* =====================================================================
   3. Lienzo
   A pantalla completa: sin ancho máximo. En monitores anchos el espacio
   se reparte entre las columnas, no se deja en blanco a los lados.
   ===================================================================== */

.lienzo {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: .75rem;
}
@media (min-width: 1200px) { .lienzo { padding-left: 1rem; padding-right: 1rem; } }

/* Un módulo que llena el alto disponible: encabezado y herramientas ocupan
   lo suyo y el último hijo se estira. Si el contenido no cabe, el lienzo
   desplaza como siempre. */
.modulo-lleno {
  display: flex;
  flex-direction: column;
  min-height: 100%;
}
.modulo-lleno > * { flex: none; }
.modulo-lleno > .crece { flex: 1 1 auto; min-height: 0; }

/* `fijo` es para los módulos donde el desplazamiento debe vivir dentro de la
   lista, no en el lienzo: con `min-height` la tabla crecía a sus 50 filas y
   empujaba la página entera. Con alto definido, el encabezado y las
   herramientas conservan su tamaño y la lista se queda con el resto. */
.modulo-lleno.fijo { height: 100%; min-height: 0; }

/* =====================================================================
   4. Encabezado de página  ·  .slds-page-header
   ===================================================================== */

.encabezado {
  background: var(--panel);
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--radio);
  box-shadow: var(--sombra-1);
  padding: .75rem 1rem;
  margin-bottom: .75rem;
}
.encabezado.pegado { border-radius: var(--radio) var(--radio) 0 0; box-shadow: none; margin-bottom: 0; }
.encabezado-fila { display: flex; align-items: flex-start; gap: .75rem; }
.encabezado-titulo { flex: 1 1 0; min-width: 0; }

.migas { display: flex; align-items: center; gap: .35rem; font-size: 12px; color: var(--texto-3); margin-bottom: .1rem; }
.migas button { border: 0; background: none; padding: 0; color: var(--marca-osc); cursor: pointer; }
.migas button:hover { text-decoration: underline; }

.rotulo-objeto { font-size: 11px; color: var(--texto-3); }
.encabezado h1 {
  margin: 0;
  font-size: 20px; font-weight: 700; line-height: 1.2;
  letter-spacing: -.01em;
}

.acciones-pagina { display: flex; gap: .25rem; flex: none; flex-wrap: wrap; justify-content: flex-end; }

/* Bloques de detalle bajo el título — .slds-page-header__detail-row */
.detalle-fila {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: .75rem 1.5rem;
  margin: .75rem -1rem -.75rem;
  padding: .75rem 1rem;
  background: var(--panel-2);
  border-top: 1px solid var(--linea);
  border-radius: 0 0 var(--radio) var(--radio);
}
.detalle-bloque .rot {
  font-size: 11px; font-weight: 600; color: var(--texto-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.detalle-bloque .val { font-size: 13px; font-weight: 600; }

/* Icono de objeto: el cuadrado redondeado de color de Lightning */
.icono-objeto {
  display: grid; place-items: center;
  width: 2.25rem; height: 2.25rem; flex: none;
  border-radius: var(--radio-g);
  color: #fff;
}
.icono-objeto .icono { width: 1.25rem; height: 1.25rem; }
.icono-objeto.oportunidad { background: var(--ventus-naranja); }
.icono-objeto.proyecto    { background: var(--marca); }
.icono-objeto.mercado     { background: var(--ventus-azul-oscuro); }
.icono-objeto.inicio      { background: var(--ventus-azul-claro); }
.icono-objeto.chico       { width: 1.5rem; height: 1.5rem; border-radius: var(--radio); }
.icono-objeto.chico .icono { width: .875rem; height: .875rem; }

/* =====================================================================
   5. Botones
   ===================================================================== */

.boton {
  display: inline-flex; align-items: center; gap: .375rem;
  height: 2rem; padding: 0 .75rem;
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--radio);
  background: var(--panel);
  color: var(--marca-osc);
  font-size: 13px;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .15s, border-color .15s;
}
.boton:hover { background: var(--panel-3); text-decoration: none; }
.boton:disabled { color: var(--texto-3); background: var(--panel-3); cursor: not-allowed; }
.boton.principal {
  background: var(--marca-osc);
  border-color: var(--marca-osc);
  color: #fff;
  font-weight: 600;
}
.boton.principal:hover:not(:disabled) { background: var(--marca-prof); border-color: var(--marca-prof); }
.boton.principal:disabled { background: var(--panel-3); border-color: var(--linea-fuerte); color: var(--texto-3); }
.boton.icono-solo { width: 2rem; padding: 0; justify-content: center; }

/* =====================================================================
   6. Tarjetas
   ===================================================================== */

.tarjeta {
  background: var(--panel);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra-1);
  margin-bottom: .75rem;
}
.tarjeta > header {
  display: flex; align-items: center; gap: .5rem;
  padding: .625rem .75rem;
  border-bottom: 1px solid var(--linea);
}
.tarjeta > header h3 { margin: 0; font-size: 14px; font-weight: 700; flex: 1; min-width: 0; }
.tarjeta > header .conteo { font-size: 12px; font-weight: 400; color: var(--texto-3); }
.tarjeta .cuerpo { padding: .75rem; }
.tarjeta .cuerpo.sin-relleno { padding: 0; }
.tarjeta > footer {
  padding: .4rem .75rem;
  border-top: 1px solid var(--linea);
  background: var(--panel-2);
  border-radius: 0 0 var(--radio) var(--radio);
  text-align: center;
}

/* =====================================================================
   7. Indicadores
   ===================================================================== */

.indicadores {
  display: grid;
  /* 11,5rem y no 13,5: con 13,5 las cinco tarjetas de Inicio partían en 4+1
     por debajo de 1.150 px de ancho y quedaba una huérfana. */
  grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr));
  gap: .75rem;
  margin-bottom: .75rem;
}
.indicador {
  position: relative;
  padding: .875rem 1rem .875rem 1.125rem;
  background: var(--panel);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra-1);
  overflow: hidden;
}
.indicador::before {
  content: ""; position: absolute; inset: 0 auto 0 0;
  width: 4px; background: var(--marca);
}
.indicador.acento-2::before { background: var(--ventus-azul-claro); }
.indicador.acento-3::before { background: var(--ventus-naranja); }
.indicador.acento-4::before { background: var(--ventus-verde-claro); }
.indicador .rot {
  font-size: 11px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--texto-3);
}
/* Sin `tabular-nums`: a este tamaño las cifras de ancho fijo se ven sueltas.
   Las tabulares quedan para donde los números se alinean en columna. */
.indicador .val {
  font-size: clamp(24px, 2.2vh + 12px, 34px);
  font-weight: 300; line-height: 1.2;
  letter-spacing: -.02em;
}
.indicador .val small { font-size: 15px; font-weight: 400; color: var(--texto-2); margin-left: .15rem; }
.indicador .pie { font-size: 12px; color: var(--texto-3); }

/* =====================================================================
   8. Ruta de etapas  ·  .slds-path
   La punta de flecha son dos rectángulos sesgados 28° y -30°, exactamente
   como en Lightning. La diferencia con Salesforce es de color, no de
   forma: allá el tramo recorrido es verde de "correcto"; aquí el verde es
   la marca, así que el tramo recorrido va en verde tenue con visto bueno
   y la etapa actual va en verde sólido.
   ===================================================================== */

.ruta { padding: .625rem .75rem .75rem; }
.ruta-pista { display: flex; align-items: center; gap: 1.25rem; }
.ruta-nav {
  display: flex; align-items: flex-start; flex: 1; min-width: 0; overflow: hidden;
  list-style: none; margin: 0; padding: 0;
}

.ruta-item {
  position: relative;
  flex: 1;
  min-width: 4.5rem;
  margin-left: .375rem;
  margin-right: .4375rem;
  text-align: center;
  background: var(--panel-3);
}
.ruta-item::before, .ruta-item::after {
  content: ""; position: absolute;
  left: -.25rem; right: -.3125rem;
  background: inherit;
}
.ruta-item::before { top: 0;    height: calc(1rem + .0625rem); transform: skew(28deg)  translate3d(0,0,0); }
.ruta-item::after  { bottom: 0; height: 1rem;                  transform: skew(-30deg) translate3d(0,0,0); }

.ruta-item:first-child {
  margin-left: 0; padding-left: .625rem;
  border-radius: 2rem 0 0 2rem;
}
.ruta-item:first-child::before, .ruta-item:first-child::after { left: 1.125rem; }
.ruta-item:last-child {
  margin-right: 0; padding-right: .625rem;
  border-radius: 0 2rem 2rem 0;
}
.ruta-item:last-child::before, .ruta-item:last-child::after { right: .625rem; }

.ruta-enlace {
  position: relative; z-index: 5;
  display: flex; align-items: center; justify-content: center; gap: .3rem;
  width: 100%; height: 2rem;
  padding: .5rem .25rem .5rem .5rem;
  border: 0; background: none;
  color: var(--texto-2);
  font-size: 12px;
}
.ruta-enlace .rot { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ruta-enlace .icono { width: .75rem; height: .75rem; }

.ruta-item.recorrida { background: var(--marca-16); }
.ruta-item.recorrida .ruta-enlace { color: var(--marca-prof); font-weight: 600; }
.ruta-item.actual { background: var(--marca); }
.ruta-item.actual .ruta-enlace { color: #fff; font-weight: 700; }
.ruta-item.ganada { background: var(--exito); }
.ruta-item.perdida { background: var(--critico); }
.ruta-item.pausada { background: var(--alerta); }
.ruta-item.ganada .ruta-enlace,
.ruta-item.perdida .ruta-enlace,
.ruta-item.pausada .ruta-enlace { color: #fff; font-weight: 700; }

.ruta-accion { flex: none; display: flex; align-items: center; gap: .5rem; }

/* =====================================================================
   9. Barra de herramientas de la lista
   ===================================================================== */

.herramientas {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  padding: .5rem .75rem;
  background: var(--panel);
  border: 1px solid var(--linea-fuerte);
  border-top: 0;
  border-bottom: 0;
}
.herramientas .separa { flex: 1; }
.herramientas .resumen { font-size: 12px; color: var(--texto-3); }

.campo-busqueda { position: relative; }
.campo-busqueda .icono {
  position: absolute; left: .5rem; top: 50%;
  transform: translateY(-50%); fill: var(--texto-3); pointer-events: none;
}
input[type="search"], select, input[type="text"] {
  height: 2rem;
  padding: 0 .5rem;
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--radio);
  background: var(--panel);
  color: var(--texto);
}
input[type="search"] { padding-left: 2rem; min-width: 15rem; }
select { cursor: pointer; }
input:focus, select:focus, textarea:focus {
  outline: 0;
  border-color: var(--marca);
  box-shadow: 0 0 0 1px var(--marca);
}

/* Selector de vistas guardadas */
.vistas { display: flex; gap: .25rem; flex-wrap: wrap; }
.vista-guardada {
  height: 1.75rem; padding: 0 .625rem;
  border: 1px solid var(--linea-fuerte);
  border-radius: 999px;
  background: var(--panel);
  color: var(--texto-2);
  font-size: 12px;
  cursor: pointer;
}
.vista-guardada:hover { background: var(--panel-3); }
.vista-guardada[aria-pressed="true"] {
  background: var(--marca-10);
  border-color: var(--marca);
  color: var(--marca-prof);
  font-weight: 600;
}

/* Conmutador tabla / kanban */
.conmutador { display: flex; border: 1px solid var(--linea-fuerte); border-radius: var(--radio); overflow: hidden; }
.conmutador button {
  display: grid; place-items: center;
  width: 2rem; height: 2rem;
  border: 0; background: var(--panel); color: var(--texto-2); cursor: pointer;
}
.conmutador button + button { border-left: 1px solid var(--linea-fuerte); }
.conmutador button[aria-pressed="true"] { background: var(--marca-16); color: var(--marca-prof); }

/* =====================================================================
   10. Tabla de la lista
   ===================================================================== */

/* La lista desplaza dentro de su propia caja, como en Lightning, y así el
   encabezado de columna se queda fijo. Ojo: al ser contenedor de scroll,
   un menú posicionado dentro quedaría recortado — por eso los menús de
   fila se dibujan en `position: fixed` colgados del cuerpo. */
.envoltura-tabla {
  overflow: auto;
  background: var(--panel);
  border: 1px solid var(--linea-fuerte);
  border-radius: 0 0 var(--radio) var(--radio);
  box-shadow: var(--sombra-1);
}
table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead th {
  position: sticky; top: 0;
  z-index: 2;
  padding: .5rem .75rem;
  background: var(--panel-2);
  border-bottom: 1px solid var(--linea-fuerte);
  text-align: left;
  font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--texto-3);
  white-space: nowrap;
}
thead th.ordenable { cursor: pointer; user-select: none; }
thead th.ordenable:hover { background: var(--marca-10); color: var(--marca-prof); }
thead th .orden { opacity: 0; margin-left: .2rem; }
thead th[aria-sort] { color: var(--marca-prof); }
thead th[aria-sort] .orden { opacity: 1; }
tbody td { padding: .4rem .75rem; border-bottom: 1px solid var(--linea); vertical-align: middle; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--marca-04); }
.enlace-registro {
  color: var(--marca-osc); font-weight: 600; cursor: pointer;
  background: none; border: 0; padding: 0; text-align: left;
  font: inherit; font-weight: 600;
}
.enlace-registro:hover { text-decoration: underline; }
th.col-acciones, td.col-acciones { width: 2.5rem; padding-left: 0; padding-right: .25rem; }
.nada {
  padding: 3rem 1rem; text-align: center; color: var(--texto-3);
}
.nada strong { display: block; color: var(--texto-2); margin-bottom: .25rem; }

/* Menú de acciones por fila */
.menu-fila { position: relative; }
.menu-fila > button {
  display: grid; place-items: center;
  width: 1.75rem; height: 1.75rem;
  border: 1px solid transparent; border-radius: var(--radio);
  background: none; color: var(--texto-3); cursor: pointer;
}
tbody tr:hover .menu-fila > button { border-color: var(--linea-fuerte); background: var(--panel); }
.menu-fila > button:hover { color: var(--marca-osc); }
.menu-desplegable {
  position: fixed;
  z-index: 150; min-width: 14rem;
  padding: .25rem 0;
  background: var(--panel);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra-3);
}
.menu-desplegable button {
  display: flex; align-items: center; gap: .5rem;
  width: 100%; padding: .4rem .75rem;
  border: 0; background: none; text-align: left; cursor: pointer;
  color: var(--texto);
}
.menu-desplegable button:hover { background: var(--marca-10); }
.menu-desplegable hr { border: 0; border-top: 1px solid var(--linea); margin: .25rem 0; }

/* =====================================================================
   11. Distintivos de estado
   Ninguno usa el verde de marca. El oliva dice "correcto"; el verde de
   Ventus dice "Ventus".
   ===================================================================== */

.distintivo {
  display: inline-flex; align-items: center; gap: .25rem;
  padding: .05rem .45rem;
  border: 1px solid var(--neutro-borde);
  border-radius: 999px;
  background: var(--neutro-fondo);
  color: var(--neutro);
  font-size: 11.5px; font-weight: 600;
  white-space: nowrap;
}
.distintivo::before { content: ""; width: .375rem; height: .375rem; border-radius: 50%; background: currentColor; }
.distintivo.sin-punto::before { display: none; }
.d-exito   { background: var(--exito-fondo);   border-color: var(--exito-borde);   color: var(--exito); }
.d-alerta  { background: var(--alerta-fondo);  border-color: var(--alerta-borde);  color: var(--alerta); }
.d-critico { background: var(--critico-fondo); border-color: var(--critico-borde); color: var(--critico); }
.d-info    { background: var(--info-fondo);    border-color: var(--info-borde);    color: var(--info); }
.d-marca   { background: var(--marca-10);      border-color: var(--marca-30);      color: var(--marca-prof); }

/* =====================================================================
   12. Kanban del embudo
   ===================================================================== */

.kanban {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(15rem, 1fr);
  gap: .5rem;
  padding: .75rem;
  overflow-x: auto;
  background: var(--panel);
  border: 1px solid var(--linea-fuerte);
  border-top: 0;
  border-radius: 0 0 var(--radio) var(--radio);
}
.kanban-col {
  display: flex; flex-direction: column;
  background: var(--panel-3);
  border-radius: var(--radio);
  min-height: 8rem;
}
.kanban-col > header {
  padding: .5rem .625rem;
  border-bottom: 2px solid var(--marca);
}
.kanban-col.cerrada > header { border-bottom-color: var(--neutro-borde); }
.kanban-col.exito   > header { border-bottom-color: var(--exito); }
.kanban-col.perdida > header { border-bottom-color: var(--critico); }
.kanban-col.alerta  > header { border-bottom-color: var(--alerta); }
.kanban-col h4 {
  margin: 0; font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--texto-3);
}
.kanban-col .meta { font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
/* El alto lo fija `.kanban.crece` más abajo, que siempre aplica porque el
   kanban se emite con esa clase. Aquí sólo el desplazamiento. */
.kanban-col .lista { display: flex; flex-direction: column; gap: .375rem; padding: .375rem; overflow-y: auto; scrollbar-width: thin; }

.ficha {
  width: 100%; text-align: left;
  padding: .5rem .625rem;
  background: var(--panel);
  border: 1px solid var(--linea);
  border-left: 3px solid var(--marca);
  border-radius: var(--radio);
  box-shadow: var(--sombra-1);
  cursor: pointer;
}
.ficha:hover { border-color: var(--marca); box-shadow: var(--sombra-2); }
.ficha.f-exito   { border-left-color: var(--exito); }
.ficha.f-perdida { border-left-color: var(--critico); }
.ficha.f-alerta  { border-left-color: var(--alerta); }
.ficha .tit { font-weight: 600; font-size: 12.5px; line-height: 1.35; }
.ficha .cli { color: var(--texto-3); font-size: 12px; }
.ficha .fila {
  display: flex; justify-content: space-between; gap: .5rem;
  margin-top: .35rem; font-size: 11.5px; color: var(--texto-2);
  font-variant-numeric: tabular-nums;
}

/* =====================================================================
   13. Ficha de registro
   ===================================================================== */

.registro {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: .75rem;
  align-items: start;
}
@media (max-width: 1100px) { .registro { grid-template-columns: 1fr; } }

/* Campos en columnas */
.campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 0 2rem;
}
.campo { padding: .4rem 0; border-bottom: 1px solid var(--linea); }
.campo .rot { font-size: 11.5px; font-weight: 600; color: var(--texto-3); }
.campo .val { font-size: 13px; word-break: break-word; }
.campo .val.vacia { color: var(--texto-3); font-style: italic; }

.pestanas-registro { display: flex; border-bottom: 1px solid var(--linea); padding: 0 .75rem; }
.pestanas-registro button {
  position: relative;
  padding: .5rem .75rem;
  border: 0; background: none; color: var(--texto-2);
  font-size: 13px; cursor: pointer;
}
.pestanas-registro button[aria-selected="true"] { color: var(--marca-prof); font-weight: 700; }
.pestanas-registro button[aria-selected="true"]::after {
  content: ""; position: absolute; left: .25rem; right: .25rem; bottom: -1px;
  height: 2px; background: var(--marca);
}

.linea-tiempo { list-style: none; margin: 0; padding: 0; }
.linea-tiempo li {
  position: relative;
  margin-left: .3rem;
  padding: .1rem 0 .75rem 1.25rem;
  border-left: 1px solid var(--linea);
}
.linea-tiempo li:last-child { border-left-color: transparent; padding-bottom: 0; }
.linea-tiempo li::before {
  content: ""; position: absolute; left: -.3125rem; top: .35rem;
  width: .625rem; height: .625rem; border-radius: 50%;
  background: var(--marca); border: 2px solid var(--panel);
}
.linea-tiempo .cuando { font-size: 11.5px; color: var(--texto-3); }

/* =====================================================================
   14. Barras horizontales
   ===================================================================== */

.barras { display: flex; flex-direction: column; gap: .25rem; }
.barra-fila {
  display: grid;
  grid-template-columns: minmax(8rem, 18rem) 1fr 3rem;
  gap: .625rem; align-items: center;
  padding: .2rem 0;
}
.barra-fila .nom { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.barra-fila .pista { height: 1rem; background: var(--panel-3); border-radius: 2px; overflow: hidden; }
.barra-fila .relleno { height: 100%; background: var(--ventus-azul-oscuro); border-radius: 2px; }
.barra-fila .relleno.propio { background: var(--marca); }
.barra-fila .cif { text-align: right; font-size: 12.5px; font-variant-numeric: tabular-nums; font-weight: 600; }

/* Embudo horizontal del inicio */
.embudo-mini { display: flex; flex-direction: column; gap: .3rem; }
.embudo-paso { display: grid; grid-template-columns: 11rem 1fr auto; gap: .625rem; align-items: center; }
.embudo-paso .nom { font-size: 12.5px; }
.embudo-paso .pista { height: 1.5rem; background: var(--panel-3); border-radius: var(--radio); }
.embudo-paso .relleno {
  height: 100%;
  display: flex; align-items: center; padding-left: .5rem;
  background: var(--marca); color: #fff;
  font-size: 11.5px; font-weight: 700;
  border-radius: var(--radio);
  min-width: 1.75rem;
}
.embudo-paso.cerrada .relleno { background: var(--neutro); }
.embudo-paso.exito   .relleno { background: var(--exito); }
.embudo-paso.perdida .relleno { background: var(--critico); }
.embudo-paso.alerta  .relleno { background: var(--alerta); }
.embudo-paso .cif { font-size: 12px; color: var(--texto-3); font-variant-numeric: tabular-nums; }

/* =====================================================================
   15. Avisos, modal, carga
   ===================================================================== */

.aviso {
  display: flex; gap: .5rem; align-items: flex-start;
  padding: .625rem .75rem;
  border: 1px solid var(--info-borde);
  border-left: 3px solid var(--info);
  border-radius: var(--radio);
  background: var(--info-fondo);
  color: var(--texto-2);
  margin-bottom: .75rem;
}
.aviso .icono { fill: var(--info); margin-top: .15rem; }
.aviso.critico { border-color: var(--critico-borde); border-left-color: var(--critico); background: var(--critico-fondo); }
.aviso.critico .icono { fill: var(--critico); }
.aviso.alerta { border-color: var(--alerta-borde); border-left-color: var(--alerta); background: var(--alerta-fondo); }
.aviso.alerta .icono { fill: var(--alerta); }

.cargando { padding: 2.5rem; text-align: center; color: var(--texto-3); }
.esqueleto {
  height: .75rem; border-radius: 2px;
  background: linear-gradient(90deg, var(--panel-3) 25%, var(--linea) 37%, var(--panel-3) 63%);
  background-size: 400% 100%;
  animation: brillo 1.4s ease infinite;
}
@keyframes brillo { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

.velo {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  padding: 1rem;
  background: rgba(24, 24, 24, .55);
}
/* El ancho de los diálogos, elegido MIDIENDO el 17-sep-2026 y no a ojo.
 *
 * `100%` es el ancho del área del velo, que ya descuenta su `padding: 1rem`:
 * equivale al `96vw` de la intención, pero sin contar la barra de
 * desplazamiento —con `vw` el diálogo se pasa de ancho cuando la hay—.
 *
 * **40rem (640 px) para los diálogos cortos.** Antes eran 34rem (544). Se
 * midió el alto de los ocho paneles de la barra verde entre 544 y 800 px de
 * ancho: cuatro de ellos —descargar, favoritos, lo que me toca y reporte— dan
 * exactamente el mismo alto en todo ese rango, y los que mejoran lo hacen poco
 * (ayuda 554→534, sesión 822→783, notificaciones 437→418, todo a partir de
 * 672). O sea: **ensanchar un panel de texto no gana alto**, sólo alarga la
 * línea de lectura. 640 px es el punto en que el diálogo deja de verse
 * apretado sin pasar de ~90 caracteres por renglón.
 *
 * **60rem (960 px) para los que llevan tabla (`.ancho`).** Aquí el ancho sí
 * compra algo, y se midió dónde deja de comprarlo con «Quién firma qué»:
 *   modal 544 → la tabla desborda 131 px de lado · fila de 111,8 px (6 renglones)
 *   modal 720 → primer ancho SIN desplazamiento horizontal (la tabla pide 673)
 *   modal 880 → fila de 92,1 px
 *   modal 960 → fila de 75,5 px · tabla completa de 1.285 px
 *   modal 1040 y 1120 → **fila de 75,5 px y tabla de 1.252/1.236**: ya no mejora
 * Por eso 960 y no más: pasado ese punto sólo se estaría comiendo la pantalla
 * a cambio de nada. A 1920 ocupa la mitad justa de la ventana.
 *
 * El aparte de antes decía `max-width` sobre un `width` fijo de 34rem, así que
 * `.ancho` **no ensanchaba nada**: los nueve paneles medían 544 px, con tabla
 * o sin ella. Ese era el bulto del problema que reportó Carlos.
 */
.modal {
  width: min(40rem, 100%);
  /* El tope de alto y, sobre todo, el desplazamiento DENTRO del cuerpo: antes
     desplazaba el diálogo entero y se iban con él el título y los botones del
     pie, que es justo lo que no debe moverse. */
  max-height: min(92vh, 56rem);
  display: flex; flex-direction: column;
  overflow: hidden;
  background: var(--panel);
  border-radius: var(--radio-g);
  box-shadow: var(--sombra-3);
}
.modal > header {
  display: flex; align-items: center; gap: .5rem;
  flex: 0 0 auto;
  padding: .875rem 1rem;
  border-bottom: 1px solid var(--linea);
}
.modal > header h2 { margin: 0; font-size: 16px; font-weight: 700; flex: 1; }
.modal .cuerpo {
  padding: 1rem;
  display: flex; flex-direction: column; gap: .75rem;
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
}
.modal > footer {
  display: flex; justify-content: flex-end; gap: .5rem;
  flex: 0 0 auto;
  padding: .75rem 1rem;
  border-top: 1px solid var(--linea);
  background: var(--panel-2);
  border-radius: 0 0 var(--radio-g) var(--radio-g);
}
.campo-form { display: flex; flex-direction: column; gap: .25rem; }
.campo-form label { font-size: 12px; font-weight: 600; color: var(--texto-2); }
.campo-form label .req { color: var(--critico); }
.campo-form select, .campo-form textarea, .campo-form input { width: 100%; }
.campo-form textarea {
  min-height: 5rem; padding: .5rem; resize: vertical;
  border: 1px solid var(--linea-fuerte); border-radius: var(--radio);
  background: var(--panel);
}
.campo-form .pista { font-size: 11.5px; color: var(--texto-3); }

/* =====================================================================
   16. Adaptación a pantallas pequeñas
   ===================================================================== */

@media (max-width: 900px) {
  .logotipo i { display: none; }
  .nombre-app { display: none; }
  .barra-modulos { padding-left: .5rem; }
  .indicador .val { font-size: 24px; }
  .detalle-fila { grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); }
}

@media (max-width: 700px) {
  .logotipo b { font-size: 14px; }
  .buscador { min-width: 6rem; }
  .acciones-globales button.opcional { display: none; }
  .encabezado h1 { font-size: 17px; }
  .acciones-pagina .boton span { display: none; }
  .acciones-pagina .boton { padding: 0 .5rem; }
  .herramientas input[type="search"] { min-width: 0; flex: 1; }
  .barra-fila { grid-template-columns: minmax(6rem, 1fr) 2fr 2.5rem; }
  .embudo-paso { grid-template-columns: 7rem 1fr auto; }
  .ruta-pista { flex-direction: column; align-items: stretch; gap: .5rem; }
  .ocultable { display: none; }
  /* Los filtros de región y país miden 12rem cada uno y `flex: none` no los
     dejaba bajar de línea: a 390 px la página desplazaba 140 px de lado. */
  .encabezado-fila { flex-wrap: wrap; }
  .acciones-pagina { flex: 1 1 100%; justify-content: flex-start; }
  .acciones-pagina .entrada { flex: 1 1 8rem; min-width: 0; }
  /* Con filas de alto automático la serie mensual quedaba en 48 px. */
  .tablero .columnas-plot { min-height: 10rem; }

  /* En un teléfono el diálogo vale más ancho que margen: con 1rem por lado el
     modal medía 360 de 392; con .5rem mide 376. */
  .velo { padding: .5rem; }
}

/* =====================================================================
   17. Tablero directivo

   Los colores de gráfico no se eligieron a ojo: se validaron con el
   comprobador del kit de visualización, en claro y en oscuro.

   · Embudo — las etapas son una secuencia, así que llevan **rampa
     ordinal** de un solo tono (el verde de marca), no ocho colores.
     Pasa monotonía de luminosidad, salto mínimo entre pasos y contraste
     del extremo claro. Las etapas de cierre son **estado**, no serie, y
     llevan los tokens semánticos.
   · Serie mensual — forma de **énfasis**: lo ganado en oliva, el resto
     en gris de contexto. Verde contra rojo colapsa bajo deuteranopía
     (ΔE 1,3); oliva contra gris se separa por luminosidad y lo distingue
     cualquiera. El gris queda por debajo de 3:1 contra el panel a
     propósito: por eso cada gráfico trae rótulos directos y su tabla.
   · Magnitudes nominales (departamento, cliente, servicio) — **un solo
     tono para todas las barras**. Colorear cada barra según su valor
     gastaría el canal de identidad en repetir lo que ya dice el largo.
   ===================================================================== */

:root {
  /* Rampa ordinal del embudo: un tono, tres pasos, claro a oscuro */
  --etapa-1: #4FB894;
  --etapa-2: #008F5F;
  --etapa-3: #004A31;

  /* Énfasis: lo destacado contra el contexto */
  --serie-foco:  #4F7A24;
  --serie-resto: #D4D7D9;

  /* Magnitud nominal: una sola serie */
  --serie-magnitud: #04708E;

  --rejilla: rgba(0, 0, 0, .09);
}

@media (prefers-color-scheme: dark) {
  :root {
    --etapa-1: #1E6B4E;
    --etapa-2: #2FB98A;
    --etapa-3: #8FE7C6;
    --serie-foco:  #A9CE72;
    --serie-resto: #3A4043;
    --serie-magnitud: #5FC3E0;
    --rejilla: rgba(255, 255, 255, .10);
  }
}

/* ---------- Rejilla del tablero ---------- */

.tablero {
  display: grid;
  gap: .75rem;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-auto-rows: minmax(13rem, 1fr);
  min-height: 0;
}
.tablero > .tarjeta {
  margin: 0;
  display: flex; flex-direction: column;
  min-height: 0; min-width: 0;
}
.tablero > .tarjeta > .cuerpo {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column;
}

.cel-3  { grid-column: span 3; }
.cel-4  { grid-column: span 4; }
.cel-5  { grid-column: span 5; }
.cel-6  { grid-column: span 6; }
.cel-7  { grid-column: span 7; }
.cel-8  { grid-column: span 8; }
.cel-9  { grid-column: span 9; }
.cel-12 { grid-column: span 12; }

@media (max-width: 1250px) {
  .cel-5, .cel-7, .cel-8, .cel-9 { grid-column: span 12; }
  .cel-3, .cel-4 { grid-column: span 6; }
}
@media (max-width: 780px) {
  .cel-3, .cel-4, .cel-6 { grid-column: span 12; }
  .tablero { grid-auto-rows: minmax(12rem, auto); }
}

/* ---------- Conmutador gráfico / tabla en la cabecera ---------- */

.tarjeta > header .util { display: flex; align-items: center; gap: .25rem; flex: none; }

.boton-mini {
  height: 1.5rem; padding: 0 .5rem;
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--radio);
  background: var(--panel);
  color: var(--texto-2);
  font-size: 11.5px;
  cursor: pointer;
}
.boton-mini:hover { background: var(--panel-3); }
.boton-mini[aria-pressed="true"] {
  background: var(--marca-10);
  border-color: var(--marca);
  color: var(--marca-prof);
  font-weight: 600;
}

/* ---------- Leyenda ---------- */

.leyenda {
  flex: none;
  display: flex; flex-wrap: wrap; gap: .25rem .875rem;
  padding-bottom: .5rem;
  font-size: 11.5px; color: var(--texto-2);
}
.leyenda span { display: inline-flex; align-items: center; gap: .35rem; }
.leyenda i { width: .625rem; height: .625rem; border-radius: 2px; flex: none; }

/* ---------- Nota al pie del gráfico ---------- */

.nota-grafico {
  flex: none;
  margin: .5rem 0 0;
  font-size: 11.5px; line-height: 1.45;
  color: var(--texto-3);
}

/* ---------- Barras horizontales ---------- */

.barras-h {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column;
  gap: 2px;                    /* la separación entre marcas es hueco, no borde */
  overflow-y: auto;
}
.barra-h {
  flex: 1 1 0; min-height: 1.3rem;
  display: grid;
  grid-template-columns: minmax(5rem, 9.5rem) minmax(0, 1fr) auto;
  gap: .5rem; align-items: center;
}
.barra-h > .rot {
  font-size: 12px; color: var(--texto-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.barra-h > .pista {
  height: 100%; max-height: 1.6rem; min-height: .7rem;
  display: flex; align-items: center;
}
.barra-h .marca {
  height: 100%;
  min-width: 2px;
  border-radius: 0 4px 4px 0;   /* extremo redondeado, anclado a la línea base */
  background: var(--serie-magnitud);
}
.barra-h > .cif {
  font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--texto); white-space: nowrap;
}
.barra-h > .cif small { font-weight: 400; color: var(--texto-3); }

/* Embudo: cada etapa toma su paso de la rampa; los cierres, su estado */
.barra-h.e1 .marca      { background: var(--etapa-1); }
.barra-h.e2 .marca      { background: var(--etapa-2); }
.barra-h.e3 .marca      { background: var(--etapa-3); }
.barra-h.alerta  .marca { background: var(--alerta); }
.barra-h.exito   .marca { background: var(--exito); }
.barra-h.critico .marca { background: var(--critico); }

/* ---------- Columnas apiladas de la serie mensual ---------- */

.columnas { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }

.columnas-plot {
  position: relative;
  flex: 1 1 auto; min-height: 3rem;
  display: flex; align-items: flex-end; gap: 2px;
  border-bottom: 1px solid var(--linea-fuerte);
}
/* Rejilla de fondo en líneas continuas y discretas, nunca punteadas */
.columnas-plot::before {
  content: ""; position: absolute; inset: 0;
  pointer-events: none;
  background-image: repeating-linear-gradient(
    to top,
    transparent 0, transparent calc(25% - 1px),
    var(--rejilla) calc(25% - 1px), var(--rejilla) 25%);
}
.col-mes {
  position: relative; z-index: 1;
  flex: 1 1 0; min-width: 3px; height: 100%;
  display: flex; flex-direction: column; justify-content: flex-end;
}
.col-mes .seg { width: 100%; min-height: 1px; }
.col-mes .seg.foco  { background: var(--serie-foco); }
.col-mes .seg.resto { background: var(--serie-resto); }
.col-mes .seg:first-child { border-radius: 3px 3px 0 0; }
.col-mes:hover .seg { outline: 2px solid var(--panel); outline-offset: -2px; }

.columnas-eje {
  flex: none;
  display: flex; gap: 2px;
  padding-top: .25rem;
  font-size: 10px; color: var(--texto-3);
}
.columnas-eje > span {
  flex: 1 1 0; min-width: 3px;
  text-align: center;
  overflow: hidden; white-space: nowrap;
}

/* ---------- Medidor: una razón contra su límite ---------- */

.medidor {
  height: .375rem;
  margin: .3rem 0 .15rem;
  background: var(--panel-3);
  border-radius: 999px;
  overflow: hidden;
}
.medidor > i { display: block; height: 100%; border-radius: 999px; background: var(--exito); }

/* ---------- Tabla gemela de cada gráfico ---------- */

.tabla-datos { flex: 1 1 auto; min-height: 0; overflow: auto; }
.tabla-datos table { font-size: 12px; }
.tabla-datos th {
  position: sticky; top: 0;
  padding: .35rem .5rem;
  background: var(--panel-2);
  font-size: 10.5px;
}
.tabla-datos td { padding: .25rem .5rem; }

/* ---------- Indicador con desglose ---------- */

.indicador { display: flex; flex-direction: column; justify-content: center; }
.indicador .desglose {
  display: flex; flex-wrap: wrap; gap: .1rem .75rem;
  margin-top: .25rem;
  font-size: 11.5px; color: var(--texto-2);
}
.indicador .desglose b {
  font-weight: 600; color: var(--texto);
  font-variant-numeric: tabular-nums;
}

/* En pantallas bajas todo se comprime antes de empezar a desplazar. El corte
   era 760 y dejaba fuera al portátil de 768 de alto, justo el caso que más
   lo necesita. */
@media (max-height: 800px) {
  .indicadores { grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: .5rem; }
  .indicador { padding: .5rem .75rem .5rem .875rem; }
  .indicador .val { font-size: 21px; }
  .tablero { grid-auto-rows: minmax(11rem, 1fr); gap: .5rem; }
}

/* Énfasis en el módulo de mercado: Ventus es el sujeto de la comparación */
.barra-h.propio .marca { background: var(--marca); }
.barra-h.propio > .rot { color: var(--texto); font-weight: 600; }

/* Un kanban que llena el alto reparte el espacio entre sus columnas */
.kanban.crece { min-height: 0; }
.kanban.crece .kanban-col { min-height: 0; }
.kanban.crece .kanban-col .lista { max-height: none; flex: 1 1 auto; min-height: 0; }

/* =====================================================================
   18. Embudo, mapa de calor y promotores

   Rampa del mapa validada como secuencial: un solo tono, luminosidad
   monótona, salto mínimo entre pasos y extremo claro por encima de 2:1
   contra el panel, en claro y en oscuro. Los cortes son cuartiles.
   ===================================================================== */

:root {
  /* Mapa de calor: rampa secuencial de un solo tono, claro a oscuro */
  --calor-0: #EDEFF0;   /* sin proyectos */
  --calor-1: #5FBE9B;
  --calor-2: #0E9668;
  --calor-3: #00714A;
  --calor-4: #003D28;
}

@media (prefers-color-scheme: dark) {
  :root {
    --calor-0: #24282B;
    --calor-1: #1B5C43;
    --calor-2: #2B8C67;
    --calor-3: #43BC8F;
    --calor-4: #8FE7C6;
  }
}

/* ---------- Embudo ---------- */

/* El primer paso es el total: va en neutro para que la rampa verde quede
   sólo sobre los pasos del recorrido. */
.barra-h.total .marca { background: var(--neutro); }
.barra-h.total > .rot { font-weight: 700; color: var(--texto); }
.barra-h.resto .marca { background: var(--neutro-borde); }

.embudo-h .barra-h > .cif { min-width: 4.5rem; }

.salidas {
  flex: none;
  display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .5rem;
  margin-top: .625rem; padding-top: .5rem;
  border-top: 1px solid var(--linea);
}
.rotulo-salidas {
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--texto-3);
  margin-right: .25rem;
}
.salida {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .1rem .45rem;
  border: 1px solid var(--neutro-borde);
  border-radius: 999px;
  background: var(--neutro-fondo);
  color: var(--neutro);
  font-size: 11.5px;
}
.salida b { font-variant-numeric: tabular-nums; }
.salida.mala   { background: var(--critico-fondo); border-color: var(--critico-borde); color: var(--critico); }
.salida.espera { background: var(--alerta-fondo);  border-color: var(--alerta-borde);  color: var(--alerta); }

/* ---------- Serie mensual: una barra por mes, con su cifra encima ---------- */

.col-mes .valor-col {
  position: absolute; top: 0; left: 0; right: 0;
  text-align: center;
  font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--texto-2);
  pointer-events: none;
}
.col-mes { padding-top: 1.1rem; }
.col-mes .seg.magnitud { background: var(--serie-magnitud); border-radius: 3px 3px 0 0; }
.col-mes:hover .seg.magnitud { background: var(--marca); }
.columnas-eje > span { font-size: 10.5px; }

/* ---------- Indicador: unidad y meta alcanzada ---------- */

.indicador .val .unidad {
  font-size: 13px; font-weight: 600; color: var(--texto-3);
  margin-right: .25rem; vertical-align: .35em;
}
.indicador .desglose .logrado b { color: var(--exito); }

/* ---------- Mapa de calor ---------- */

.mapa {
  position: relative;
  flex: 1 1 auto; min-height: 10rem;
}
/* El SVG se ancla a la caja: dentro de un contenedor flexible, `height:100%`
   sobre un elemento reemplazado no resuelve y el mapa se queda en cero. */
.mapa svg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
}
/* El trazo del color del panel separa los departamentos sin dibujar un
   borde encima de la marca: es hueco, no línea. */
.mapa .dep { stroke: var(--panel); stroke-width: 1.2; stroke-linejoin: round; }
.mapa .dep.c0 { fill: var(--calor-0); }
.mapa .dep.c1 { fill: var(--calor-1); }
.mapa .dep.c2 { fill: var(--calor-2); }
.mapa .dep.c3 { fill: var(--calor-3); }
.mapa .dep.c4 { fill: var(--calor-4); }
.mapa .dep:hover { stroke: var(--texto); stroke-width: 1.6; }

.leyenda-mapa i.c0 { background: var(--calor-0); }
.leyenda-mapa i.c1 { background: var(--calor-1); }
.leyenda-mapa i.c2 { background: var(--calor-2); }
.leyenda-mapa i.c3 { background: var(--calor-3); }
.leyenda-mapa i.c4 { background: var(--calor-4); }
.leyenda-mapa .unidad-leyenda { color: var(--texto-3); }

/* ---------- Tabla de promotores ---------- */

.tabla-datos.crece { flex: 1 1 auto; min-height: 0; }
.tabla-datos tbody tr:hover { background: var(--marca-04); }

@media (max-width: 1250px) {
  .tarjeta.cel-4[style*="span 2"] { grid-row: span 1 !important; }
}

/* Las barras del embudo llenan su fila: con cinco pasos en una tarjeta alta,
   la marca fina dejaba más aire que dato. */
.embudo-h .barra-h > .pista { max-height: 2.4rem; }
.embudo-h .barra-h { min-height: 1.6rem; }
.embudo-h .barra-h > .cif { min-width: 6rem; text-align: right; }
.embudo-h .barra-h > .cif small { display: block; font-size: 10.5px; line-height: 1.2; }

/* =====================================================================
   Cinta de «Ver como» — herramienta de prueba
   =====================================================================
   Fija arriba del todo y en naranja de alerta, no en el verde de marca: no
   es un estado normal de la aplicación, y tiene que interrumpir. Empuja el
   resto de la página en vez de flotar encima, para no tapar la barra global.

   Sólo aparece en desarrollo: el servidor no ofrece los perfiles cuando
   VENTUS_ENTORNO=produccion, así que en producción este bloque nunca se usa.
   ===================================================================== */

#cinta-ver-como {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .4rem .9rem;
  background: var(--alerta-fondo);
  border-bottom: 1px solid var(--alerta-borde);
  color: var(--alerta);
  font-size: .82rem;
}

#cinta-ver-como .icono { flex: none; width: 1rem; height: 1rem; }
#cinta-ver-como span { flex: 1; min-width: 0; }
#cinta-ver-como b { font-weight: 600; }
#cinta-ver-como .boton { flex: none; padding: .15rem .55rem; font-size: .78rem; }

/* Una pestaña oculta no debe dejar su hueco. */
.barra-modulos .modulo[hidden] { display: none; }

/* =====================================================================
   La puerta de entrada
   =====================================================================
   Sustituye a la aplicación entera, no se superpone: un modal que se cierra
   con Escape no es una puerta. La barra global y la de módulos se ocultan,
   porque enseñar el buscador y las pestañas de algo a lo que no se ha entrado
   es enseñar lo que hay detrás.
   ===================================================================== */

body.sin-entrar .barra-global,
body.sin-entrar .barra-modulos { display: none; }

.puerta {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 1.5rem;
  background: var(--fondo);
}

.puerta-caja {
  width: min(26rem, 100%);
  /* `--panel` y `--texto`, los mismos tokens que usa cualquier tarjeta. La
     primera versión puso `var(--superficie, #fff)` — una variable que no
     existe en este proyecto— así que caía al blanco del fallback mientras el
     texto seguía tomando el color del tema oscuro. Blanco sobre blanco: la
     pantalla estaba, y no se leía. */
  background: var(--panel);
  color: var(--texto);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra-3, var(--sombra-2));
  padding: 1.75rem;
  display: flex;
  flex-direction: column;
  gap: .75rem;
}

.puerta-caja .pista { color: var(--texto-2); }

.puerta-caja .logotipo { margin-bottom: .25rem; }
.puerta-caja h2 { margin: 0; font-size: 1.15rem; }
.puerta-campos { display: flex; flex-direction: column; gap: .6rem; }
.boton.ancho { width: 100%; justify-content: center; }

/* =====================================================================
   Zona de carga de documentos
   =====================================================================
   La caja punteada que espera un archivo. Se usa dentro de los formularios
   por etapa: cada área carga lo suyo donde le toca, y la caja dice de antemano
   qué acepta y hasta cuánto — enterarse del límite al fallar la subida es
   perder el trabajo dos veces.

   Cuatro estados y cada uno se ve distinto: en reposo, con el archivo encima
   (`.encima`), subiendo (`.subiendo`) y con el archivo ya puesto (`.puesta`).
   Sin el segundo, arrastrar es un acto de fe.
   ===================================================================== */

.zona-carga {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: 11rem;
  padding: 1.5rem 1.25rem;
  text-align: center;
  background: var(--fondo);
  border: 2px dashed var(--linea-fuerte);
  border-radius: var(--radio);
  cursor: pointer;
  transition: border-color .12s, background .12s;
}

.zona-carga:hover,
.zona-carga:focus-visible { border-color: var(--marca); }

.zona-carga.encima {
  border-color: var(--marca);
  border-style: solid;
  background: var(--marca-04);
}

.zona-carga.subiendo,
.zona-carga.puesta { cursor: default; border-style: solid; }
.zona-carga.puesta { border-color: var(--exito-borde); background: var(--exito-fondo); }

.zona-carga input[type="file"] { display: none; }

.zona-carga .redondel {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  background: var(--marca-10);
  color: var(--marca);
  flex: none;
}
.zona-carga .redondel .icono { width: 1.5rem; height: 1.5rem; }
.zona-carga.puesta .redondel { background: var(--exito-fondo); color: var(--exito); }

.zona-carga .titulo { font-weight: 600; color: var(--marca-osc, var(--marca)); }
.zona-carga.puesta .titulo { color: var(--texto); }
.zona-carga .limite { font-size: .8rem; color: var(--texto-3); }

/* La barra de progreso ocupa el borde inferior: no desplaza nada al aparecer. */
.zona-carga .progreso {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 3px;
  background: var(--linea);
  border-radius: 0 0 var(--radio) var(--radio);
  overflow: hidden;
}
.zona-carga .progreso > i {
  display: block; height: 100%; width: 0;
  background: var(--marca);
  transition: width .15s linear;
}

/* Cada documento ya cargado, con lo que hace falta para confiar en él. */
.lista-adjuntos { display: flex; flex-direction: column; gap: .4rem; margin-top: .6rem; }
.adjunto {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: .6rem;
  align-items: center;
  padding: .5rem .65rem;
  background: var(--panel);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  font-size: .85rem;
}
.adjunto .nombre { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adjunto .meta { color: var(--texto-3); font-size: .78rem; }

/* =====================================================================
   Panel de bitácora
   ===================================================================== */

.rotulo-bloque {
  /* La fuente del sistema, como el resto. La primera versión pedía «Saira
     Condensed» copiándolo del tablero —que sí la carga de Google Fonts— y
     aquí caía a Arial: un solo panel con otra tipografía. La aplicación usa
     fuentes del sistema a propósito, para verse igual sin red durante una
     demostración. */
  font-family: var(--fuente);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .1em;
  font-size: .72rem;
  color: var(--texto-3);
  margin: 1.1rem 0 .4rem;
}
.rotulo-bloque:first-child { margin-top: 0; }

.chips { display: flex; flex-wrap: wrap; gap: .35rem; margin-bottom: .5rem; }

/* `.chip` NO tenía forma propia: sólo existían los modificadores semánticos
   (.e-ok, .e-aviso…), así que un chip neutro —«Renovables y O&M», «perfil de
   demostración»— salía como texto suelto y no se leía como una etiqueta. Se le
   da la forma aquí, y los modificadores siguen poniendo el color encima. */
.chip {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .12rem .5rem;
  border: 1px solid var(--linea);
  border-radius: 999px;
  background: var(--fondo);
  color: var(--texto-2);
  font-size: .76rem;
  font-weight: 600;
  white-space: nowrap;
}

/* Campo de texto de formulario. Estaba en uso —la puerta de entrada y la
   pantalla de asignaciones— y sin regla propia: heredaba el aspecto del
   navegador, que en oscuro sale blanco sobre blanco. */
.entrada {
  padding: .38rem .55rem;
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  background: var(--fondo);
  color: var(--texto);
  font: inherit;
  font-size: .85rem;
  min-width: 12rem;
}
.entrada:focus-visible { outline: 2px solid var(--marca); outline-offset: 1px; }
.entrada::placeholder { color: var(--texto-3); }

/* Formularios de alta manual. Dos columnas en pantalla ancha, una en
   estrecha: un formulario de ocho campos en una sola columna obliga a
   desplazarse para ver lo que ya se escribió. */
.rejilla-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: .7rem .9rem; }
.campo-form { display: flex; flex-direction: column; gap: .25rem; margin-top: .6rem; }
.campo-form > span { font-size: .78rem; font-weight: 600; color: var(--texto-2); }
.campo-form .entrada { width: 100%; min-width: 0; }
.campo-form textarea.entrada { resize: vertical; font: inherit; font-size: .85rem; }
.rejilla-form .campo-form { margin-top: 0; }

/* Una acción con su explicación al lado, sin que la explicación la empuje. */
.fila-acciones {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .8rem;
  margin: .8rem 0 .4rem;
}
.fila-acciones .pista { flex: 1 1 16rem; margin: 0; }

/* Semántica del resultado: separada del verde de marca a propósito, porque
   «salió bien» no es lo mismo que «es de Ventus». */
.e-ok      { color: var(--exito);   background: var(--exito-fondo);   border: 1px solid var(--exito-borde); }
.e-aviso   { color: var(--alerta);  background: var(--alerta-fondo);  border: 1px solid var(--alerta-borde); }
.e-alerta  { color: var(--alerta);  background: var(--alerta-fondo);  border: 1px solid var(--alerta-borde); }
.e-critico { color: var(--critico); background: var(--critico-fondo); border: 1px solid var(--critico-borde); }
td.e-ok, td.e-aviso, td.e-alerta, td.e-critico { background: none; border: 0; font-weight: 600; }

/* El alto de la tabla sigue siendo suyo y no del cuerpo, a propósito: el
   encabezado va `position: sticky` contra el ancestro con `overflow`, así que
   si el desplazamiento se llevara al cuerpo los títulos de columna dejarían de
   quedarse arriba. Lo que cambia es el tope: era fijo —15rem y 22rem— y dejaba
   media pantalla vacía en un monitor grande. Ahora crece con la ventana y
   conserva el tope en rem para que en una pantalla muy alta no se vuelva una
   lista interminable. */
.modal .tabla-datos { max-height: min(42vh, 22rem); overflow: auto; margin-bottom: .3rem; }

/* Un modal con tabla de cuatro columnas y un campo de texto no cabe en el
   ancho por omisión, que está pensado para listas de dos. */
.modal.ancho { width: min(60rem, 100%); }
.modal.ancho .tabla-datos { max-height: min(56vh, 40rem); }
.modal.ancho .tabla-datos td { vertical-align: top; }
.modal .tabla-datos table { font-size: .82rem; }
.modal .tabla-datos code { font-size: .78rem; }

/* La columna «Cambiar» de «Quién firma qué», medida: `.entrada` trae
   `min-width: 12rem` porque nació para los formularios de alta, donde el campo
   ocupa su renglón. Dentro de una celda de tabla ese mínimo clavaba la columna
   en 192 px **más** el botón, que no cabía al lado y caía debajo — de ahí los
   renglones de más en cada fila. Aquí el campo pide 11rem pero puede encoger,
   y campo y botón se quedan en la misma línea. */
.modal .tabla-datos .entrada { min-width: 0; width: 11rem; }
.modal .tabla-datos td:has(> .entrada) { white-space: nowrap; }

/* En un teléfono el campo y su botón SÍ deben apilarse, y el campo tiene que
   poder encogerse hasta el ancho de su columna. Medido a 392 px: con el
   `nowrap` de escritorio la columna «Cambiar» se clava en 283 px y la tabla
   pide 703 px de lado —peor que los 628 de antes—; así pide 630, con la
   columna en 127.
   Va AQUÍ y no en la sección 16 —que es donde vive el resto de lo adaptativo—
   porque la sección 16 está antes en el archivo: con la misma especificidad
   gana la regla posterior, y desde allí este bloque no hacía nada. Se
   comprobó midiendo: la tabla seguía pidiendo 703. */
@media (max-width: 700px) {
  .modal .tabla-datos td:has(> .entrada) { white-space: normal; }
  .modal .tabla-datos .entrada { width: 100%; }
}

/* =====================================================================
   La etapa de presupuestación, dentro de la ficha de oportunidad
   ===================================================================== */

.avance-etapa { display: flex; flex-direction: column; gap: .4rem; margin-bottom: .8rem; }
.avance-etapa .barra { height: 6px; background: var(--superficie-2, var(--fondo)); border-radius: 3px; overflow: hidden; }
.avance-etapa .barra > i { display: block; height: 100%; background: var(--marca); transition: width .2s; }
.avance-cifras { display: flex; flex-wrap: wrap; gap: .25rem 1.1rem; font-size: .83rem; color: var(--texto-2); }
.avance-cifras b { color: var(--texto); }

/* Lo que bloquea se ve distinto de lo que sólo avisa. Pintarlos igual
   convertiría una recomendación en una barrera. */
.aviso.critico { border-color: var(--critico-borde); background: var(--critico-fondo); color: var(--critico); }
.lista-motivos { margin: .35rem 0 0; padding-left: 1.1rem; display: flex; flex-direction: column; gap: .2rem; }

.plegable { margin: .5rem 0; font-size: .85rem; }
.plegable summary { cursor: pointer; color: var(--texto-2); }
.plegable summary:hover { color: var(--texto); }

.hitos { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: .5rem; }
.hito {
  display: flex; align-items: center; gap: .55rem;
  padding: .55rem .7rem;
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  background: var(--fondo);
  font-size: .85rem;
  color: var(--texto-3);
}
.hito.puesto { border-color: var(--exito-borde); background: var(--exito-fondo); color: var(--exito); }
.hito b { display: block; color: var(--texto); font-weight: 600; }
.hito.puesto b { color: var(--texto); }
.hito span { font-size: .78rem; }

tr.fila-vencida td { background: var(--critico-fondo); }

/* El pie de un bloque de cabecera: la cobertura del dato, sin ocupar sitio. */
.detalle-bloque .pie-bloque {
  font-size: .68rem;
  color: var(--texto-3);
  line-height: 1.2;
  margin-top: .1rem;
}

/* La cobertura de los MWp en la cabecera de columna: más pequeña que la cifra
   y en gris, porque es una salvedad sobre el número, no otro número. */
.kanban-col header .meta.cobertura { font-size: .68rem; color: var(--texto-3); margin-top: .1rem; }

/* =====================================================================
   El embudo de Inicio, con forma de embudo
   =====================================================================
   Dos capas superpuestas: el SVG dibuja los trapecios y una rejilla encima
   pone los rótulos. Separarlos evita el problema clásico de meter texto en
   un SVG con `preserveAspectRatio="none"` — el estiramiento horizontal
   deforma las letras. El texto es HTML normal y no se deforma. */

.embudo-svg { position: relative; margin: .3rem 0 .6rem; }
/* Alto FIJO, no `auto`. Con `height:auto` el navegador respeta la proporción
   del viewBox (100 de ancho por 46 px de paso) y sobre una tarjeta de 500 px
   el embudo salía de más de mil píxeles de alto. Aquí el eje vertical sólo
   separa pasos —no mide nada— así que se deforma a propósito con
   `preserveAspectRatio="none"` y se fija al alto que ocupan los rótulos, que
   es lo que los mantiene alineados con sus tramos. */
/* El SVG va ABSOLUTO dentro de su caja. En flujo normal su alto natural es
   el ancho por la proporción del viewBox —más de mil píxeles en una tarjeta
   ancha—, y aunque `max-height` lo recortaba, ese alto natural seguía
   entrando al cálculo de la rejilla: las dos filas del tablero medían 570-610
   px en cualquier pantalla, y en un portátil de 768 de alto el Inicio
   ocupaba el doble de la ventana. Medido el 17-sep-2026. Fuera del flujo, el
   alto lo decide sólo la tarjeta. */
.embudo-svg { min-height: calc(var(--pasos) * 34px); }
.embudo-svg svg { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }

/* La tarjeta marcada como `estirable` ocupa todo su hueco de la rejilla y le
   pasa el alto sobrante al embudo. Antes el embudo medía 46 px por paso —230
   en total— y en una pantalla alta dejaba medio recuadro vacío debajo.
   El SVG usa `preserveAspectRatio="none"`, así que estirarse verticalmente no
   lo deforma: el eje vertical sólo separa pasos, no mide nada. */
.tarjeta.estirable { display: flex; flex-direction: column; }
.tarjeta.estirable > .cuerpo {
  flex: 1; display: flex; flex-direction: column; min-height: 0;
}
.tarjeta.estirable .embudo-svg {
  flex: 1 1 auto;
  /* Suelo: por debajo de esto los rótulos de los cinco pasos se pisan. */
  min-height: calc(var(--pasos) * 42px);
  /* Y TECHO, que la primera versión no tenía: con `flex:1` a secas el embudo
     se comía los 1.400 px de una tarjeta estirada por la rejilla y quedaban
     cinco franjas enormes. Ochenta px por paso es donde el trapecio se lee
     bien sin volverse un cartel. */
  max-height: calc(var(--pasos) * 80px);
  /* Cuando el techo corta, el sobrante se reparte arriba y abajo en vez de
     quedar todo bajo las salidas. */
  margin-block: auto;
}
/* El suelo baja con el alto de la pantalla: con 42 px por paso, en un monitor
   de 1080 el tablero pasaba 60 px de la ventana (por eso el corte es 1100 y no 1000), y en uno de 768 el embudo
   solo imponía el alto de toda la fila. A 28 px el rótulo (12,5 px) aún cabe
   holgado en su tramo. */
@media (max-height: 1100px) {
  .tarjeta.estirable .embudo-svg { min-height: calc(var(--pasos) * 28px); }
  /* Mismo criterio para las barras: la de clientes tiene 11 y con 1,3rem cada
     una era ella la que fijaba el alto de la fila. 16 px aún deja la barra
     más gruesa que el texto de su rótulo. */
  .barra-h { min-height: 1rem; line-height: 1.25; }
}
/* Filas iguales que se reparten el alto real, sea el que sea. Con
   `grid-auto-rows` fijo los rótulos se despegaban de sus tramos en cuanto la
   tarjeta crecía. */
.embudo-rotulos { grid-auto-rows: 1fr; }
/* Los cinco tramos con opacidad CRECIENTE sobre el mismo verde: el paso más
   avanzado es el más sólido. La primera versión usaba `--marca-16` y
   `--marca-30`, que son rgba de muy baja opacidad pensadas para fondos
   claros; sobre el fondo oscuro se veían los cinco iguales y el embudo
   parecía una sola figura. Se comprobó en pantalla.

   El borde no es adorno: sin él, dos tramos contiguos de opacidad parecida se
   funden y desaparece el escalón, que es justo lo que hay que ver. */
.embudo-svg .tramo {
  fill: var(--marca); stroke: var(--panel); stroke-width: .4;
  transition: fill-opacity .15s;
}
.embudo-svg .tramo.total  { fill-opacity: .28; }
.embudo-svg .tramo.e1     { fill-opacity: .45; }
.embudo-svg .tramo.e2     { fill-opacity: .62; }
.embudo-svg .tramo.e3     { fill-opacity: .80; }
.embudo-svg .tramo.exito  { fill: var(--exito); fill-opacity: .95; }
.embudo-svg .tramo:hover  { fill-opacity: 1; }

/* Los rótulos van encima, en una rejilla de filas de la misma altura que los
   tramos del SVG. `pointer-events:none` deja pasar el cursor al trapecio para
   que su `<title>` siga apareciendo. */
.embudo-rotulos {
  position: absolute; inset: 0; display: grid;
  grid-auto-rows: 1fr; pointer-events: none;
}
.paso-rot {
  display: flex; align-items: center; gap: .5rem;
  padding: 0 .7rem; font-size: .78rem; color: var(--texto);
}
.paso-rot .et { flex: 1; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.paso-rot .ci { font-weight: 700; font-variant-numeric: tabular-nums; }
.paso-rot .cv { font-size: .68rem; color: var(--texto-3); min-width: 5.2rem; text-align: right; }

/* Cabeceras ordenables de la tabla de proyectos. La flecha ocupa sitio
   siempre, aunque esté vacía: sin eso la cabecera salta de ancho al ordenar. */
th.ordenable { cursor: pointer; user-select: none; }
th.ordenable:hover { color: var(--marca-osc); }
th.ordenable .flecha { display: inline-block; min-width: .7em; margin-left: .15em; color: var(--marca); }
/* =====================================================================
   Pestaña Datos y reporte de impresión
   ===================================================================== */

/* --- el catálogo de fuentes --- */

.col-marca { width: 2.5rem; text-align: center; }
.col-marca input { cursor: pointer; }

/* La fila que separa una fuente de la siguiente. No es una fila de datos, así
   que no se comporta como tal: ni pasa el ratón por encima ni se puede marcar. */
tr.fila-grupo > td {
  background: var(--panel-2);
  border-top: 1px solid var(--linea-fuerte);
  font-size: .8rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: .45rem .75rem;
}
tr.fila-grupo > td .resumen { text-transform: none; letter-spacing: 0; margin-left: .5rem; }
tr.fila-grupo:hover > td { background: var(--panel-2); }

/* Lo que el rol no puede descargar. Se atenúa, no se esconde: saber que la
   fuente existe es parte de saber qué hay. */
tr.vetada { opacity: .55; }
tr.vetada code { text-decoration: line-through; text-decoration-thickness: 1px; }

.lista-lisa { list-style: none; margin: .5rem 0 0; padding: 0; display: grid; gap: .3rem; }
.lista-lisa li {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; padding: .35rem .55rem; border-radius: var(--radio);
  background: var(--panel-2);
}

.botonera-atajos { display: flex; gap: .4rem; flex-wrap: wrap; margin: .75rem 0; }

.rejilla-marcas { display: grid; gap: .35rem; }
.marca-modulo {
  display: flex; align-items: flex-start; gap: .55rem;
  padding: .5rem .6rem; border: 1px solid var(--linea);
  border-radius: var(--radio); cursor: pointer;
}
.marca-modulo:hover { border-color: var(--marca); background: var(--marca-04); }
.marca-modulo em { display: block; font-style: normal; font-size: .78rem; }

/* =====================================================================
   El documento de impresión
   =====================================================================
   Vive oculto en la pantalla y sólo existe en el papel. Se compone con los
   datos que ya están cargados, no re-consultando: el reporte tiene que decir
   lo mismo que la pantalla desde la que se pidió.
   ===================================================================== */

#impresion { display: none; }

@media print {
  /* Fuera todo lo de la aplicación. Se oculta por elemento y no con un
     `body > * { display:none }`, que también se llevaría por delante el
     propio contenedor del reporte. */
  .barra-global, .barra-modulos, .lienzo, #capa-modal { display: none !important; }

  #impresion { display: block; }

  @page { size: A4; margin: 14mm 12mm; }

  html, body {
    background: #fff !important;
    color: #111 !important;
    font-size: 10pt;
    /* La aplicación fija `body { height: 100dvh; overflow: hidden; display: flex }`
       para que el lienzo scrollee por dentro. Al imprimir eso recorta el
       documento a la altura de una pantalla: salía la portada y nada más.
       Se deshacen las tres cosas, y por eso van con !important — la regla de
       arriba no está dentro de ninguna consulta de medios. */
    height: auto !important;
    overflow: visible !important;
    display: block !important;
  }

  .p-portada { padding-bottom: 1rem; border-bottom: 2px solid #00734D; }
  .p-marca { font-size: 9pt; letter-spacing: .08em; text-transform: uppercase; color: #00734D; }
  .p-portada h1 { font-size: 22pt; margin: .2rem 0 .8rem; }

  .p-meta {
    display: grid; grid-template-columns: repeat(4, 1fr);
    gap: .5rem 1rem; margin-bottom: .8rem;
  }
  .p-meta span { display: block; font-size: 8pt; text-transform: uppercase;
                 letter-spacing: .05em; color: #555; }
  .p-meta b { font-size: 10pt; }

  .p-seccion { break-inside: auto; }
  /* Cada sección menos la primera empieza en hoja nueva: un comité pasa
     páginas por módulo, no busca dónde acabó el anterior. */
  .p-seccion.salto { break-before: page; }
  .p-seccion > h2 {
    font-size: 14pt; margin: 0 0 .6rem;
    padding-bottom: .25rem; border-bottom: 1px solid #00734D; color: #00734D;
  }
  .p-sub { font-size: 11pt; margin: 1rem 0 .35rem; }

  .p-cifras {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: .6rem; margin-bottom: .9rem;
  }
  .p-cifra { border: 1px solid #ddd; border-left: 3px solid #00734D;
             padding: .4rem .55rem; break-inside: avoid; }
  .p-rot { font-size: 7.5pt; text-transform: uppercase; letter-spacing: .05em; color: #555; }
  /* 13pt y no 15: con cinco tarjetas en A4 cada una mide unos 34 mm, y a 15pt
     «USD 175,1 M» partía en dos líneas y descuadraba la fila. */
  .p-val { font-size: 13pt; font-weight: 700; font-variant-numeric: tabular-nums;
           line-height: 1.15; }
  .p-det { font-size: 8pt; color: #444; }

  .p-tabla { width: 100%; border-collapse: collapse; font-size: 8.5pt; }
  .p-tabla th {
    background: #00734D; color: #fff; text-align: left;
    padding: .3rem .4rem; font-size: 8pt;
    /* Sin esto Chrome imprime las cabeceras en blanco sobre blanco para
       «ahorrar tinta», y la tabla sale sin encabezado. */
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  /* La cabecera se repite en cada hoja: una tabla de cuatrocientas filas
     sin encabezado a partir de la página dos es ilegible. */
  .p-tabla thead { display: table-header-group; }
  .p-tabla td { padding: .25rem .4rem; border-bottom: 1px solid #e5e5e5;
                vertical-align: top; }
  .p-tabla tr { break-inside: avoid; }
  .p-tabla td:nth-child(n+3) { font-variant-numeric: tabular-nums; }

  .p-nota { font-size: 8pt; color: #444; margin: .45rem 0 0; break-inside: avoid; }
  .p-aviso {
    font-size: 8.5pt; margin: .5rem 0 0; padding: .4rem .55rem;
    border-left: 3px solid #B45309; background: #FEF6E7;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
    break-inside: avoid;
  }
  .p-nada { font-size: 9pt; color: #666; font-style: italic; }

  .p-pie {
    margin-top: 1.2rem; padding-top: .4rem; border-top: 1px solid #ddd;
    font-size: 7.5pt; color: #666;
  }
}

/* =====================================================================
   «Sin contacto» — la columna anterior al embudo
   =====================================================================
   Se distingue a propósito del resto del kanban: son PROYECTOS, no
   oportunidades, y no suman al valor del embudo. El borde discontinuo lo dice
   antes de que nadie lea la nota.
   ===================================================================== */

.kanban-col.sin-contacto {
  border: 1px dashed var(--linea-fuerte);
  background: var(--panel-2);
}
.kanban-col.sin-contacto > header h4::before {
  content: "";
  display: inline-block;
  width: .5rem; height: .5rem; margin-right: .4rem;
  border: 1px dashed var(--texto-3);
  border-radius: 2px;
  vertical-align: middle;
}

.nota-columna {
  font-size: .78rem;
  line-height: 1.45;
  color: var(--texto-2);
  padding: .5rem .6rem;
  margin-bottom: .5rem;
  border-left: 2px solid var(--linea-fuerte);
  background: var(--fondo);
  border-radius: var(--radio);
}

/* La tarjeta de proyecto NO es un botón: no lleva a ninguna ficha de
   oportunidad porque todavía no hay ninguna. Darle el mismo aspecto
   pulsable que `.ficha` prometería una navegación que no existe. */
.ficha.f-sin-contacto {
  cursor: default;
  border-style: dashed;
  display: block;
  width: 100%;
  text-align: left;
}

.ficha .fila.candidato {
  margin-top: .35rem;
  padding-top: .35rem;
  border-top: 1px solid var(--linea);
  color: var(--alerta);
  gap: .35rem;
  align-items: center;
}
.ficha .fila.candidato .icono { width: .85rem; height: .85rem; flex: none; }

.acciones-ficha {
  display: flex;
  gap: .35rem;
  margin-top: .5rem;
  flex-wrap: wrap;
}

/* Botón pequeño para dentro de una tarjeta. No existía: `.boton` a secas
   ocupa toda la anchura de la columna del kanban. */
.boton.menudo {
  font-size: .74rem;
  padding: .25rem .5rem;
  gap: .25rem;
  flex: 1 1 auto;
  justify-content: center;
}
.boton.menudo .icono { width: .8rem; height: .8rem; }

/* =====================================================================
   Eje Y del gráfico de columnas
   =====================================================================
   Antes la cifra sólo aparecía sobre cada barra y al pasar el ratón. En una
   proyección, o para quien mira de lejos, no había forma de estimar una
   barra sin acercarse. El eje da esa referencia sin quitarle sitio al dato.
   ===================================================================== */

.columnas.con-eje {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "eje plot" ".   meses";
  /* SIN ESTA LÍNEA LA TARJETA DEJA UN HUECO DEBAJO DE LAS BARRAS.
     `grid-template-areas` declara dos filas y las deja en `auto`. Como
     `.columnas` sí estira —es `flex:1 1 auto` dentro del cuerpo de la
     tarjeta—, el `align-content: normal` de la rejilla se comporta como
     `stretch` y reparte el sobrante A PARTES IGUALES entre las dos filas.
     La de los meses se quedaba con la mitad aunque su texto mide 18 px.
     Medido el 17-sep-2026 en la tarjeta «Propuestas enviadas por mes»,
     fila de meses / espacio sin usar dentro de ella:
       2560×1440 → 199,9 px de fila, 181,9 sin usar (barras: 228,1 de 428)
       1920×1080 →  96,6 px de fila,  78,6 sin usar (barras: 124,9 de 221,5)
       1366× 768 →  90,2 px de fila,  72,2 sin usar (barras: 118,5 de 208,7)
       1280× 600 →  98,5 px de fila,  80,5 sin usar (barras: 126,8 de 225,3)
     `1fr auto` le da todo el sobrante al área de barras y a los meses su
     alto natural, que es lo único que necesitan. No toca el flujo del
     embudo ni los suelos de altura que se fijaron esta misma mañana. */
  grid-template-rows: 1fr auto;
  column-gap: .5rem;
}
.columnas.con-eje > .eje-y        { grid-area: eje; }
.columnas.con-eje > .columnas-plot { grid-area: plot; }
.columnas.con-eje > .columnas-eje  { grid-area: meses; }

.eje-y {
  position: relative;
  min-width: 1.6rem;
  /* La rejilla de fondo que ya trae `.columnas-plot` se apaga: con marcas de
     verdad, dos rejillas distintas se contradicen a la vista. */
}
.columnas.con-eje .columnas-plot::before { display: none; }

.marca-y {
  position: absolute;
  right: 0;
  transform: translateY(50%);
  display: flex; align-items: center; gap: .5rem;
  white-space: nowrap;
}
.marca-y span {
  font-size: .68rem;
  color: var(--texto-3);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
/* La línea sale del rótulo y cruza el área de barras. Es `position:fixed` en
   el sentido de que no puede vivir dentro de `.columnas-plot` —quedaría por
   debajo de las barras—, así que se dibuja desde el eje hacia la derecha con
   un ancho que cubre la rejilla. */
.marca-y i {
  position: absolute;
  left: calc(100% + .5rem);
  width: 100vw;
  height: 1px;
  background: var(--linea);
  pointer-events: none;
}
.eje-y { overflow: visible; }
.columnas.con-eje { overflow: hidden; }

/* Enlace dentro de un aviso: es un botón de verdad —cambia de vista— pero se
   lee como enlace porque eso es lo que la frase promete. */
.aviso .enlace {
  background: none; border: 0; padding: 0;
  color: var(--marca); font: inherit; cursor: pointer;
  text-decoration: underline; text-underline-offset: 2px;
}
.aviso .enlace:hover { color: var(--marca-osc); }
.aviso .enlace:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; }

/* =====================================================================
   El corte entre «Sin contacto» y el embudo
   =====================================================================
   Las dos partes cuentan cosas distintas: a la izquierda proyectos del SOM sin
   oferta, a la derecha oportunidades del libro comercial. Sin separación
   alguien suma 82 + 26 y le da 108, que no es ninguna cifra.

   La primera versión metía un `<div>` separador entre las dos. No funcionó:
   `.kanban` es una REJILLA con `grid-auto-columns: minmax(15rem, 1fr)`, así
   que ese div se convirtió en una columna vacía de cuatrocientos píxeles
   atravesada en medio del tablero.

   Ahora la separación vive en la propia columna —un borde a la derecha y un
   respiro— que es lo que una rejilla sí permite.
   ===================================================================== */

.kanban-col.sin-contacto {
  border-right: 2px solid var(--linea-fuerte);
  padding-right: .55rem;
  margin-right: .35rem;
}
