/* =====================================================================
   ico.css — Ico, la mascota del sistema.
   Geometria de retícula: todo sale de rectangulos y rombos a 45 grados,
   igual que los iconos. Sin SVG decorativo, sin colores nuevos: los
   valores salen de tokens.css y de config/branding.php via --brand.

   Estructura minima:

     <span class="ico ico--md ico--reposo" data-ico>
       <span class="ico__cabeza">
         <span class="ico__casco">
           <span class="ico__visor"> ojos / cifra / glifo </span>
           <span class="ico__haz"></span>
         </span>
         <span class="ico__base"></span>
       </span>
       <span class="ico__riel"> filas </span>
     </span>

   Un solo dibujo para todos los estados: lo que cambia son colores y
   transformaciones, nunca el marcado. Asi las transiciones son fluidas y
   no hay saltos entre un estado y otro.
   ===================================================================== */

/* ---------- Escala ----------
   Base (--ico-esc: 1): casco 88x68, visor 64x24, ojo 8, base 96x8.
   Las escalas elegidas caen siempre en pixeles enteros. */
.ico,
.ico-bloque { --ico-esc: 1; }

.ico--xs, .ico-bloque--xs { --ico-esc: .25; }   /* 22x17 · fila de tabla, toast */
.ico--sm, .ico-bloque--sm { --ico-esc: .5; }    /* 44x34 · junto a un campo */
.ico--md, .ico-bloque--md { --ico-esc: .75; }   /* 66x51 · tarjetas */
.ico--lg, .ico-bloque--lg { --ico-esc: 1; }     /* 88x68 · estados vacios, login */
.ico--xl, .ico-bloque--xl { --ico-esc: 1.5; }   /* 132x102 · pantallas de error */

/* ---------- Paleta por estado (variables locales) ---------- */
.ico {
  --ico-cuerpo: var(--cds-gray-80, #393939);
  --ico-visor-bg: var(--brand, #0f62fe);
  --ico-ojo: #ffffff;
  --ico-base-bg: var(--cds-gray-30, #c6c6c6);
  --ico-rombo: var(--cds-gray-30, #c6c6c6);
  --ico-barra: var(--cds-gray-20, #e0e0e0);
  --ico-barra-fondo: var(--cds-gray-20, #e0e0e0);
  /* El haz solo se dibuja en `lee`, asi que puede tener color de salida sin
     ensuciar ningun otro estado: `.ico__haz` nace en `opacity: 0` y unicamente
     `.ico--lee` lo enciende.

     Estaba en `transparent` y eso dejaba el estado sin dibujo salvo que
     alguien le pusiera ademas un origen: `--ico-haz` solo tomaba color en
     `.ico--ia` y `.ico--fuente`. Un `lee` a secas -la guia de estilo, o
     cualquier lectura que no venga de una IA ni de una fuente oficial- se
     quedaba en un visor negro y quieto. El unico sitio donde funcionaba era
     el escaner de Gastos, que lleva `origen="ia"`.

     El azul claro es el mismo que usa `fuente`, y se lee sobre el visor casi
     negro que pone `lee`. Los dos origenes siguen mandando cuando estan: van
     mas abajo en este archivo y con la misma especificidad, asi que ganan por
     orden de fuente. */
  --ico-haz: var(--cds-blue-40, #78a9ff);

  display: inline-flex;
  align-items: flex-start;
  gap: calc(8px * var(--ico-esc));
  flex: none;
  line-height: 0;
}

/* ---------- Tema oscuro ----------
   Va aqui, antes de los estados, y con :where() para no sumar especificidad.
   Escrito como `[data-theme="dark"] .ico` valia (0,2,0) y le ganaba a cada
   .ico--estado (0,1,0): en oscuro el error salia azul en vez de rojo y
   dormido perdia su gris. Ahora empata en (0,1,0) y manda el que va despues,
   que es el estado. */
:where([data-theme="dark"]) .ico {
  --ico-cuerpo: var(--cds-gray-60, #6f6f6f);
  --ico-visor-bg: var(--cds-blue-40, #78a9ff);
  --ico-ojo: var(--cds-gray-100, #161616);
  --ico-base-bg: var(--cds-gray-80, #393939);
  --ico-rombo: var(--cds-gray-70, #525252);
  /* La barra rellena tiene que igualar a su pista, igual que en claro: asi
     no se ve nada hasta que un estado la pinta (cola azul, ok verde, error
     rojo). Sin esto se quedaba en el gris claro de la base y en oscuro
     aparecian tres barras blancas llenas en reposo, busca, cifra y lee. */
  --ico-barra: var(--cds-gray-80, #393939);
  --ico-barra-fondo: var(--cds-gray-80, #393939);
}

.ico-bloque {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: calc(14px * var(--ico-esc));
}

/* ---------- Cabeza ---------- */
.ico__cabeza {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.ico__casco {
  width: calc(88px * var(--ico-esc));
  height: calc(68px * var(--ico-esc));
  background: var(--ico-cuerpo);
  display: grid;
  place-items: center;
  position: relative;
  overflow: hidden;
  transition: background .26s cubic-bezier(.2, 0, .38, .9);
}

.ico__visor {
  width: calc(64px * var(--ico-esc));
  height: calc(24px * var(--ico-esc));
  background: var(--ico-visor-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(12px * var(--ico-esc));
  transition: background .26s cubic-bezier(.2, 0, .38, .9);
}

.ico__ojo {
  /* Sin display propio se queda inline dentro de .ico__parpadeo (que si es
     hijo flex del visor) y el navegador ignora width/height: ojos de 0x0. */
  display: block;
  width: calc(8px * var(--ico-esc));
  height: calc(8px * var(--ico-esc));
  background: var(--ico-ojo);
  transform: rotate(0deg) translateY(0) scale(1, 1);
  transition: transform .24s cubic-bezier(.2, 0, .38, .9), background .26s ease;
}

/* El parpadeo va en un envoltorio para no pisar la transformacion de estado.

   Los estados sin ojos esconden ESTE envoltorio y no el ojo de dentro. Con
   `.ico__ojo { display: none }` el envoltorio seguia siendo hijo flex del
   visor: dos cajas de ancho cero, pero con sus dos huecos contando. Y como
   el visor centra su contenido, esos huecos empujaban lo que quedara -la
   cifra, el glifo del tema- exactamente un `gap` a la derecha: 6px a sm,
   12 a lg, 18 a xl. */
.ico__parpadeo { animation: ico-parpadeo 5.6s steps(1, end) infinite; }
.ico__parpadeo + .ico__parpadeo { animation-delay: .1s; }
.ico__parpadeo + .ico__parpadeo .ico__ojo { transition-delay: .04s; }

.ico__base {
  width: calc(96px * var(--ico-esc));
  height: calc(8px * var(--ico-esc));
  background: var(--ico-base-bg);
  transition: background .26s ease;
}

/* Haz de lectura: solo se enciende en los estados que esperan algo */
.ico__haz {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: calc(2px * var(--ico-esc));
  background: var(--ico-haz);
  opacity: 0;
}

/* Cifra dentro del visor (carga con porcentaje real) */
.ico__cifra {
  display: none;
  font-family: var(--font-mono, 'IBM Plex Mono', monospace);
  font-size: calc(13px * var(--ico-esc));
  line-height: 1;
  color: var(--cds-blue-40, #78a9ff);
}

/* ---------- Riel ---------- */
.ico__riel {
  display: flex;
  flex-direction: column;
  gap: calc(6px * var(--ico-esc));
  padding-top: calc(2px * var(--ico-esc));
}

/* [hidden] lo trae el navegador con especificidad cero, asi que el display
   de mas abajo le gana y lo oculto se sigue viendo. Vale para el riel y para
   el propio Ico: la guia pide que no aparezca hasta que tenga algo que
   contar, y para eso hay que poder esconderlo. */
.ico[hidden],
.ico-bloque[hidden],
.ico__fila[hidden] { display: none; }

.ico__fila {
  display: flex;
  align-items: center;
  gap: calc(6px * var(--ico-esc));
}

.ico__marcas {
  position: relative;
  width: calc(12px * var(--ico-esc));
  height: calc(12px * var(--ico-esc));
  display: grid;
  place-items: center;
  flex: none;
}

.ico__rombo {
  position: absolute;
  width: calc(8px * var(--ico-esc));
  height: calc(8px * var(--ico-esc));
  background: var(--ico-rombo);
  transform: rotate(45deg) scale(1);
  transition: opacity .2s ease, transform .24s cubic-bezier(.2, 0, .38, .9), background .26s ease;
}

.ico__check,
.ico__equis {
  position: absolute;
  width: calc(12px * var(--ico-esc));
  height: calc(12px * var(--ico-esc));
  opacity: 0;
  transform: scale(.4);
  transition: opacity .2s ease, transform .3s cubic-bezier(.2, 1.5, .4, 1);
}

/* Check y equis en el mismo idioma que el rombo: trazos a 45 grados
   exactos, remate cuadrado y esquina en punta. */
.ico__check path,
.ico__equis path {
  fill: none;
  stroke-width: 2.2;
  stroke-linecap: square;
  stroke-linejoin: miter;
}

.ico__check path { stroke: var(--support-success, #24a148); }
.ico__equis path { stroke: var(--support-error, #da1e28); stroke-width: 2; }

.ico__barra {
  width: calc(32px * var(--ico-esc));
  height: calc(6px * var(--ico-esc));
  background: var(--ico-barra-fondo);
  overflow: hidden;
  flex: none;
}

.ico__barra i {
  display: block;
  height: 100%;
  width: var(--ico-valor, 100%);
  background: var(--ico-barra);
  transform-origin: left;
  transition: width .3s cubic-bezier(.2, .6, .3, 1), background .26s ease;
}

.ico__etiqueta {
  font-family: var(--font-mono, 'IBM Plex Mono', monospace);
  font-size: calc(12px * var(--ico-esc));
  line-height: 1;
  color: var(--text-secondary, #525252);
  white-space: nowrap;
}

/* El riel se cae por debajo de 64px de casco: a ese tamano no se lee */
.ico--xs .ico__riel .ico__barra,
.ico--xs .ico__etiqueta { display: none; }
.ico--sm .ico__etiqueta { display: none; }

/* =====================================================================
   Estados
   ===================================================================== */

/* Reposo: respira y parpadea. Riel apagado si no hay dato que contar. */
/* ---------- Origen del dato: tres marcas que no se mezclan ----------
   Va antes que los estados y no despues. Con la misma especificidad (0,1,0)
   manda la regla que se declara ultima: con el origen al final, un Ico
   marcado como 'fuente' se quedaba azul aunque el estado fuera de error, y
   ningun estado podia pintar su visor. Declarado aqui, el origen pone el
   color de descanso y el estado lo pisa cuando tiene algo que decir. */

/* IA (OCR de comprobantes): violeta, tokens de Carbon for AI. Solo cuando
   hay una IA detras. */
.ico--ia {
  --ico-visor-bg: var(--ai-border-end, #8a3ffc);
  --ico-rombo: var(--ai-border-end, #8a3ffc);
  --ico-barra: var(--ai-border-end, #8a3ffc);
  --ico-haz: var(--ai-border-end, #8a3ffc);
}

/* Fuente oficial (SUNAT, RENIEC, MTC): azul de marca y sello aparte.
   Nunca tokens de IA: no es una sugerencia, es un dato autoritativo. */
.ico--fuente {
  --ico-visor-bg: var(--brand, #0f62fe);
  --ico-rombo: var(--brand, #0f62fe);
  --ico-barra: var(--brand, #0f62fe);
  --ico-haz: var(--cds-blue-40, #78a9ff);
}

/* Emitido por el propio sistema (correlativos del gestor de series):
   una tinta gris, no hay nada que verificar. */
.ico--sistema {
  --ico-cuerpo: var(--cds-gray-60, #6f6f6f);
  --ico-visor-bg: var(--cds-gray-30, #c6c6c6);
  --ico-rombo: var(--cds-gray-40, #8d8d8d);
  --ico-barra: var(--cds-gray-30, #c6c6c6);
}
.ico--sistema .ico__parpadeo { display: none; }

.ico--reposo .ico__cabeza { animation: ico-flota 6s cubic-bezier(.2, 0, .38, .9) infinite; }

/* Contrasena oculta: cierra los ojos. Es funcional, confirma el enmascarado. */
.ico--oculta .ico__ojo { transform: rotate(0deg) translateY(0) scale(1, .16); }

/* Ver contrasena: los ojos se abren un poco mas y bajan hacia el campo.
   Sin pupila: el gesto sale de la forma del ojo. */
.ico--mira .ico__ojo { transform: rotate(0deg) translateY(calc(1px * var(--ico-esc))) scale(1, 1.1); }

/* Exito: la cara dibuja el check, visor verde y los rombos del riel se
   vuelven checks tambien.

   `error` ya giraba los ojos a rombo, que es su marca; `ok` se quedaba en
   ojos cerrados y no decia lo mismo que su marca. Ahora los dos ojos son los
   dos trazos del check: el corto baja a 40 grados y el largo sube a 45, y se
   juntan en el vertice. Es el mismo idioma que .ico__check del riel, hecho
   con las piezas que Ico ya tiene, sin marcado nuevo.

   El trazo largo entra despues del corto, que es el orden en que se dibuja
   un visto a mano. */
.ico--ok { --ico-visor-bg: var(--support-success, #24a148); }
.ico--ok .ico__ojo {
  transform: translate(calc(5px * var(--ico-esc)), calc(2px * var(--ico-esc)))
             rotate(40deg) scale(1, .25);
}
.ico--ok .ico__parpadeo + .ico__parpadeo .ico__ojo {
  transform: translate(calc(-7px * var(--ico-esc)), calc(-1px * var(--ico-esc)))
             rotate(-45deg) scale(1.6, .25);
  transition-delay: .12s;
}
/* El parpadeo se para: un ojo que ya no es un ojo no parpadea. */
.ico--ok .ico__parpadeo { animation: none; }
.ico--ok .ico__cabeza { animation: ico-sello .45s cubic-bezier(.2, 0, .38, .9) both; }
.ico--ok .ico__rombo { opacity: 0; transform: rotate(45deg) scale(.4); }
.ico--ok .ico__check { opacity: 1; transform: scale(1); }
.ico--ok .ico__barra i { background: var(--support-success, #24a148); }
.ico--ok .ico__fila:nth-child(2) .ico__check { transition-delay: .05s; }
.ico--ok .ico__fila:nth-child(3) .ico__check { transition-delay: .1s; }

/* Error: ojos en rombo, equis en la primera fila y una sacudida corta.
   Tres iteraciones y para: no vibra indefinidamente. */
.ico--error { --ico-visor-bg: var(--support-error, #da1e28); }
.ico--error .ico__ojo { transform: rotate(45deg) translateY(0) scale(1, 1); }
.ico--error .ico__cabeza { animation: ico-sacudida .5s cubic-bezier(.2, 0, .38, .9) 3; }
.ico--error .ico__fila:first-child .ico__rombo { opacity: 0; transform: rotate(45deg) scale(.4); }
.ico--error .ico__fila:first-child .ico__equis { opacity: 1; transform: scale(1); }
.ico--error .ico__fila:first-child .ico__barra i { background: var(--support-error, #da1e28); }

/* Apagado: sin datos o sin API configurada. Falta de configuracion no es
   error del usuario, asi que va gris y no rojo. */
.ico--apagado {
  --ico-cuerpo: var(--cds-gray-70, #525252);
  --ico-visor-bg: var(--cds-gray-40, #a8a8a8);
  --ico-rombo: var(--cds-gray-30, #c6c6c6);
  --ico-barra: var(--cds-gray-20, #e0e0e0);
}

/* ---------- Esperas ---------- */

/* 1. Cola: en vez de los ojos, una raya que respira, y las barras del riel
      se llenan una tras otra. Una barra por modulo o por paso real del
      proceso.

      La raya es el dibujo del estado y se queda. Lo que estaba mal era el
      tamanio: 3px por la escala son 1,5px a sm y 0,75 a xs, y encima la
      mitad del tiempo al 35% de opacidad. No se veia. Ahora crece a 4px y
      nunca baja de 2, que es el suelo para que siga siendo una raya y no
      una insinuacion.

      Y estaba corrida: escondia el ojo pero no su envoltorio, asi que los
      dos huecos del visor la empujaban un gap a la derecha. Ahora se
      esconde el envoltorio, como en los demas estados sin ojos. */
.ico--cola {
  --ico-visor-bg: var(--cds-gray-100, #161616);
  --ico-rombo: var(--cds-blue-40, #78a9ff);
  --ico-barra: var(--cds-blue-40, #78a9ff);
}
.ico--cola .ico__parpadeo { display: none; }
.ico--cola .ico__visor::after {
  content: "";
  width: 62%;
  height: max(2px, calc(4px * var(--ico-esc)));
  background: var(--cds-blue-40, #78a9ff);
  animation: ico-respira 2.4s cubic-bezier(.2, 0, .38, .9) infinite;
}
.ico--cola .ico__barra i { animation: ico-cola 2.6s cubic-bezier(.2, 0, .38, .9) infinite; }
.ico--cola .ico__fila:nth-child(2) .ico__barra i { animation-delay: .35s; }
.ico--cola .ico__fila:nth-child(3) .ico__barra i { animation-delay: .7s; }
.ico--cola .ico__fila:nth-child(4) .ico__barra i { animation-delay: 1.05s; }

/* 2. Buscando: los ojos barren de lado a lado. Para esperas cortas sin
      progreso medible: una consulta, un filtro, un guardado. */
.ico--busca .ico__visor { animation: ico-busca 2.2s cubic-bezier(.45, .05, .55, .95) infinite; }
.ico--busca .ico__cabeza { animation: ico-flota 5.2s cubic-bezier(.2, 0, .38, .9) infinite; }

/* 3. Cifra: el porcentaje vive dentro del visor y sigue la curva real del
      proceso. Los rombos son hitos: 33, 66 y 90 por ciento. */
.ico--cifra { --ico-visor-bg: var(--cds-gray-100, #161616); }
.ico--cifra .ico__parpadeo { display: none; }
.ico--cifra .ico__cifra { display: block; }
.ico--cifra .ico__barra { display: none; }
.ico--cifra .ico__rombo { background: var(--cds-gray-60, #6f6f6f); }
.ico--cifra .ico__fila--hito .ico__rombo { background: var(--cds-blue-40, #78a9ff); }

.ico-progreso {
  width: calc(168px * var(--ico-esc));
  height: calc(4px * var(--ico-esc));
  background: var(--cds-gray-80, #393939);
  overflow: hidden;
}
.ico-progreso i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--cds-blue-40, #78a9ff);
  transition: width .18s linear;
}

/* 4. Lectura con haz: escaneo de comprobante, consulta a una fuente. */
.ico--lee .ico__parpadeo { display: none; }
.ico--lee { --ico-visor-bg: var(--cds-gray-100, #161616); }
.ico--lee .ico__haz {
  opacity: 1;
  animation: ico-haz 1.9s cubic-bezier(.45, .05, .55, .95) infinite;
}


/* ---------- Filas con semantica propia ---------- */
.ico__fila--ok .ico__rombo { opacity: 0; transform: rotate(45deg) scale(.4); }
.ico__fila--ok .ico__check { opacity: 1; transform: scale(1); }
.ico__fila--ok .ico__barra i { background: var(--support-success, #24a148); }

.ico__fila--error .ico__rombo { opacity: 0; transform: rotate(45deg) scale(.4); }
.ico__fila--error .ico__equis { opacity: 1; transform: scale(1); }
.ico__fila--error .ico__barra i { background: var(--support-error, #da1e28); }

/* El triangulo sustituye al rombo y se queda con el latido, que es lo que
   distingue "pide atencion ahora" de "a medias, y avisa". */
.ico__fila--alerta .ico__rombo { opacity: 0; transform: rotate(45deg) scale(.4); }
.ico__fila--alerta .ico__aviso {
  opacity: 1;
  transform: scale(1);
  color: var(--support-warning, #f1c21b);
  animation: ico-chip 2.4s ease-in-out infinite;
}
.ico__fila--alerta .ico__barra i { background: var(--support-warning, #f1c21b); }

/* Se llamaba `apagada` aqui y `neutra` en x-marca, siendo el mismo dibujo.
   Un solo nombre. */
.ico__fila--neutra .ico__rombo { background: var(--ico-rombo); }
.ico__fila--neutra .ico__barra i { background: var(--cds-gray-20, #e0e0e0); }
.ico__fila--neutra .ico__etiqueta { color: var(--cds-gray-40, #8d8d8d); }

.ico__fila--activa .ico__rombo { background: var(--brand, #0f62fe); }
.ico__fila--activa .ico__barra i { background: var(--brand, #0f62fe); }

/* =====================================================================
   Tema dia / noche
   El header se queda en Gray 100 en los dos temas (ver layout.css), asi
   que Ico vive en las capas de contenido y el que cambia es el: sirve de
   confirmacion visual de que el tema se aplico.
   ===================================================================== */
/* De noche el parpado baja: mismo dibujo, gesto distinto */
[data-theme="dark"] .ico--reposo .ico__ojo { transform: rotate(0deg) translateY(0) scale(1, .72); }

/* ---------- Ico como control de tema ---------- */
.ico--tema .ico__parpadeo { display: none; }
.ico__glifo {
  width: calc(16px * var(--ico-esc));
  height: calc(16px * var(--ico-esc));
  color: #ffffff;
}
[data-theme="dark"] .ico__glifo { color: var(--cds-gray-100, #161616); }
.ico__glifo--noche { display: none; }
.ico--noche .ico__glifo--dia { display: none; }
.ico--noche .ico__glifo--noche { display: block; }

button.ico-boton {
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  display: inline-flex;
  line-height: 0;
}

/* =====================================================================
   Movimiento
   Las animaciones acompanan esperas reales. Nada se anima si no esta
   pasando algo.
   ===================================================================== */
@keyframes ico-parpadeo {
  0%, 91%, 100% { transform: scaleY(1); }
  95% { transform: scaleY(.1); }
}
@keyframes ico-flota {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(calc(-3px * var(--ico-esc))); }
}
@keyframes ico-sacudida {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(calc(-2px * var(--ico-esc))); }
  75% { transform: translateX(calc(2px * var(--ico-esc))); }
}
@keyframes ico-sello {
  0% { transform: scale(.4); opacity: 0; }
  60% { transform: scale(1.08); }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes ico-haz {
  0% { transform: translateY(-100%); }
  55%, 56% { transform: translateY(calc(68px * var(--ico-esc))); }
  100% { transform: translateY(-100%); }
}
@keyframes ico-cola {
  0% { transform: scaleX(0); }
  70%, 100% { transform: scaleX(1); }
}

/* La raya de `cola` respira: se alarga y se aclara, se acorta y se apaga.
   No baja del 45% de opacidad, que por debajo desaparecia. */
@keyframes ico-respira {
  0%, 100% { opacity: .45; transform: scaleX(.55); }
  50%      { opacity: 1; transform: scaleX(1); }
}
@keyframes ico-busca {
  0%, 100% { transform: translateX(calc(-6px * var(--ico-esc))); }
  50% { transform: translateX(calc(6px * var(--ico-esc))); }
}
@keyframes ico-chip {
  0%, 100% { opacity: .28; }
  50% { opacity: 1; }
}

/* La presencia es informacion, no decoracion: bajo reduced-motion se corta
   el movimiento pero el estado sigue visible. */
@media (prefers-reduced-motion: reduce) {
  .ico__parpadeo,
  .ico__cabeza,
  .ico__visor,
  .ico__haz,
  .ico__barra i,
  .ico__rombo,
  .ico--cola .ico__visor::after,
  .ico__aviso { animation: none !important; }
  .ico--lee .ico__haz { opacity: 1; transform: translateY(calc(30px * var(--ico-esc))); }
  /* Sin el respirar, la raya se queda entera y opaca: la espera se sigue
     leyendo por ella y por el riel, que es lo que hay que conservar. */
  .ico--cola .ico__visor::after { opacity: 1; transform: none; }
  .ico--cola .ico__barra i { width: 100%; }
}

/* =====================================================================
   Impresion
   En papel Ico va a linea, a una sola tinta: es el sello de "esto lo
   emitio el sistema" y tiene que aguantar fotocopia.
   ===================================================================== */
@media print {
  .ico {
    --ico-cuerpo: transparent;
    --ico-visor-bg: #000;
    --ico-base-bg: #000;
    --ico-rombo: #000;
    --ico-barra: #000;
  }
  .ico__casco {
    border: 1px solid #000;
    background: none;
  }
  .ico__parpadeo { display: none; }
  .ico__haz { display: none; }
  .ico__cabeza,
  .ico__visor,
  .ico__barra i { animation: none !important; }
  .ico__base { height: 2px; }
}

/* =====================================================================
   Estados sobrios
   El color no baña la pantalla: el cuerpo se queda en grises y el acento
   entra una sola vez, en el rombo del riel o en una regla de 3px.
   ===================================================================== */

/* Aviso de tiempo (sesion por vencer, 419, informe observado): el visor
   no se pinta, el ambar vive en el riel. */
.ico--neutro {
  --ico-visor-bg: var(--cds-gray-50, #8d8d8d);
  --ico-ojo: var(--cds-gray-100, #161616);
}

/* Mantenimiento programado (503): el sistema esta dormido a proposito. */
.ico--dormido {
  --ico-visor-bg: var(--cds-gray-60, #6f6f6f);
  --ico-ojo: var(--cds-gray-100, #161616);
}
.ico--dormido .ico__ojo { transform: rotate(0deg) translateY(0) scale(1, .16); }

/* =====================================================================
   Semaforo de estados
   Cada estado necesita FORMA ademas de color: el color solo no es
   informacion accesible y no sobrevive a una impresion en blanco y negro.

     rombo hueco    todavia no          ico__fila--futura
     rombo lleno    en curso            ico__fila--activa
     rombo partido  a medias            ico__fila--parcial (ambar)
                                        ico__fila--mitad   (marca)
     check          cerrado bien        ico__fila--ok
     equis          cerrado mal         ico__fila--error
   ===================================================================== */
.ico__medio {
  position: absolute;
  width: calc(12px * var(--ico-esc));
  height: calc(12px * var(--ico-esc));
  opacity: 0;
  transform: scale(.4);
  transition: opacity .2s ease, transform .3s cubic-bezier(.2, 1.5, .4, 1);
}
.ico__medio-borde { fill: none; stroke: currentColor; stroke-width: 2; }
.ico__medio-lleno { fill: currentColor; }

/* Aviso: triangulo, no un rombo de otro color.
   `alerta` era un rombo lleno ambar, y `activa` es un rombo lleno azul: la
   misma figura con distinto color, o sea el color haciendo el trabajo que le
   toca a la forma. Quien no distingue ambar de azul veia dos marcas iguales.
   El triangulo tiene base plana y una sola punta, asi que se lee a 12px y no
   se confunde con ninguna de las otras. */
.ico__aviso {
  position: absolute;
  width: calc(12px * var(--ico-esc));
  height: calc(12px * var(--ico-esc));
  opacity: 0;
  transform: scale(.4);
  transition: opacity .2s ease, transform .3s cubic-bezier(.2, 1.5, .4, 1);
}
.ico__aviso path { fill: currentColor; }

.ico__fila--parcial .ico__rombo,
.ico__fila--mitad .ico__rombo { opacity: 0; transform: rotate(45deg) scale(.4); }
.ico__fila--parcial .ico__medio,
.ico__fila--mitad .ico__medio { opacity: 1; transform: scale(1); }
.ico__fila--parcial .ico__medio { color: var(--support-warning, #f1c21b); }
.ico__fila--mitad .ico__medio { color: var(--brand, #0f62fe); }
.ico__fila--parcial .ico__barra i { background: var(--support-warning, #f1c21b); }
.ico__fila--mitad .ico__barra i { background: var(--brand, #0f62fe); }

/* Paso que aun no ocurrio: rombo hueco, nunca gris relleno (se confundia
   con "apagado por plan"). */
.ico__fila--futura .ico__rombo {
  background: transparent;
  border: calc(2px * var(--ico-esc)) solid var(--cds-gray-30, #c6c6c6);
  box-sizing: border-box;
}
.ico__fila--futura .ico__barra i { background: var(--cds-gray-20, #e0e0e0); }

@media print {
  .ico__medio { color: #000; }
}
