/* ============================================================
   HRZN · UNIFICACION DE HERO, BARRA Y AVATAR
   ------------------------------------------------------------
   Por que una hoja nueva y no parches en las ocho existentes:

   El producto tiene DOS familias de hojas. Una mitad de las
   paginas carga horizon-skin + horizon-pages + hrzn-scale +
   hrzn-type-system; la otra carga horizon-2050-shell + la hoja
   de su pantalla. Cada familia trae su propia escala, asi que el
   MISMO componente medía distinto segun en que pagina estabas.

   Arreglarlo dentro de cada hoja significaba tocar ocho archivos
   y pelear con los !important que ya se cruzan entre ellos. Esta
   hoja se enlaza ULTIMA en las once paginas y deja la
   unificacion en un solo lugar auditable.

   Lleva !important donde tiene que ganarle a un !important que ya
   estaba. No es preferencia: es la unica forma de resolverlo sin
   reescribir la cascada de las dos familias.

   Y no son diez paginas sino ONCE documentos: FinOps no tiene su
   contenido en finops.html sino dentro del iframe de
   cockpit/app.html, que es otro documento. Esa es la razon por la
   que FinOps se quedo afuera de todo hasta que se le enlazo esta
   hoja aparte.

   MEDIDO antes de tocar, a 1440px de viewport:

     componente        antes                          ahora
     hero: numero      68 / 66.6 / 56.3px             40px
     hero: palabras    42 / 41 / 34.7px               40px
     hero: otros h1    30 / 38 / 43px                 40px
     barra utilidad    10 / 11 / 14px                 14px
     alto de barra     46 / 51 / 53px                 53px
     iniciales barra   11px, rozando el circulo       9px
     avatar perfil     40px y 44px                    40px
     veredicto         14.5 / 18px, con y sin caja    16px, sin caja
     saludo            18 / 14.5 / 9.5 / 16px         14.5px
   ============================================================ */

:root {
  /* El punto medio EXACTO entre los dos tokens que el hero venia
     usando, tomado termino a termino:

       --t-display  clamp(44px, 5.2vw, 68px)   <- el numero
       --t-page     clamp(30px, 3.2vw, 42px)   <- las palabras
       --t-hero     clamp(37px, 4.2vw, 55px)   <- el medio

     Se define como clamp y no como un valor fijo para no perder
     el comportamiento fluido que ya tenian las dos escalas.

     CORREGIDO. El punto medio daba 55px y en pantalla resulto
     enorme: el titular se comia el hero. Baja a 40px, que queda
     cerca de los 42 que tenian las PALABRAS en --t-page -- o sea
     el titular conserva su escala anterior y lo que se corrigio es
     que el numero dejo de ser mas grande que ellas.

     Los tres terminos bajan en la misma proporcion (40/55 = .727)
     para que el comportamiento fluido no cambie de forma:
     37 -> 27, 4.2vw -> 3.05vw, 55 -> 40. */
  --t-hero: clamp(27px, 3.05vw, 40px);
}

/* ============================================================
   1 · EL TITULO DEL HERO: UN SOLO TAMANO
   ------------------------------------------------------------
   El sistema partia el titulo en dos tamanos: el numero con
   --t-display y las palabras con --t-page. A 1440px eso daba
   68 contra 42 -- 26px de diferencia dentro de una misma frase.

   Ahora los dos van en --t-hero. Se igualan tambien el peso y el
   tracking, que venian distintos (800 el numero, 500 o 800 las
   palabras segun la pagina).
   ============================================================ */
.hz-hero-headline .hz-num,
.hz-hero-headline em,
.hz-hero-headline strong,
/* La familia hrzn-scale fija estos dos valores con
   `.hz-page.hz-page .hz-hero .hz-num` -> 66.56px y
   `.hz-page.hz-page .hz-hero-headline em` -> 40.96px, ambos
   !important y con especificidad (0,4,0). Enlazar esta hoja
   ultima no alcanza: hay que igualar la especificidad, no el
   orden. De ahi los selectores repetidos de abajo. */
.hz-page.hz-page .hz-hero .hz-num,
.hz-page.hz-page .hz-hero-headline .hz-num,
.hz-page.hz-page .hz-hero-headline em,
.hz-page.hz-page .hz-hero-headline > span:not(.hz-num),
.hz-page.hz-page .hz-hero-headline strong {
  font-size: var(--t-hero) !important;
  font-weight: 800 !important;
  letter-spacing: -.015em !important;
  line-height: 1.05 !important;
}

/* Las paginas cuyo hero es un <h1> suelto y no usa
   .hz-hero-headline. Venian en 30, 38 y 43px. */
.adoption-hero__copy h1,
.score-hero__copy h1,
.score-config-hero h1,
.bridge-title h1,
.hero-copy h1 {
  font-size: var(--t-hero) !important;
  font-weight: 800 !important;
  letter-spacing: -.015em !important;
  line-height: 1.05 !important;
}

/* cloudbeach.css le pone `white-space: nowrap` a su h1 con un
   tamano de 52px. A 55px y sin envolver, el titulo se sale de la
   columna. Se le devuelve el salto de linea. */
.hero-copy h1 { white-space: normal !important; }

/* ============================================================
   2 · EL COPETE, SIN CAJA
   ------------------------------------------------------------
   horizon-pages.css:333 define la regla y la escribe en el
   comentario: "el veredicto: punto + palabra + color, SIN CAJA".

   hrzn-scale.css:710 agrego una caja despues, scopeada a
   #settingsMain, para que el texto no negociara contraste con el
   video del hero. Ese problema ya lo resuelve el color, no la
   caja: horizon-pages.css:357 baja el ambar a #8A5202 dentro de
   .hz-hero, y #settingsMain redefine --hz-warn-ink al mismo
   valor. Medido, 5.20:1 sobre el lavado del hero.

   Asi que la caja sale y la regla del sistema vuelve a valer en
   las cinco paginas que usan .hz-verdict.

   El tamano tambien se unifica: venia 14.5px en la familia
   horizon-pages y 18px en las paginas con hrzn-scale.
   ============================================================ */
.hz-verdict,
#settingsMain .hz-verdict,
#settingsMain .hz-verdict.is-warn,
.hz-page.hz-page .hz-verdict {
  padding: 0 !important;
  background: none !important;
  border: 0 !important;
  border-radius: 0 !important;
  font-size: 16px !important;
  font-weight: 700 !important;
  line-height: 1.4 !important;
}

/* El punto de estado se conserva: es el ::before de 8px y es lo
   que hace legible el estado sin depender solo del color. */

/* ============================================================
   3 · LA BARRA DE UTILIDAD: UN TAMANO Y UNA ALTURA
   ------------------------------------------------------------
   Hay CUATRO nombres de clase para el mismo componente, uno por
   familia de hojas:

     .hz-utility        bridge-classic, users, insights
     .utility-pill      bridge, automations, settings
     .adoption-utility  adoption
     .score-utility     score

   Y tres tamanos: 10px en adoption, 11px en bridge / bridge-
   classic / score, 14px en el resto. En automations y settings el
   boton de periodo iba a 16px mientras sus hermanos iban a 14.

   Se unifica en 14px porque es --t-dense, que hrzn-type-system.css
   declara como "PISO del sistema": bajar de ahi contradice la
   escala, y cuatro paginas ya estaban en ese valor.

   Los selectores van con la clase repetida para poder ganarle a
   `.utility-pill.utility-pill :where(...)` de hrzn-bar.css y a
   `.utility-pill .viewers small` de horizon-skin.css, que ya
   traen !important.
   ============================================================ */
.hz-utility.hz-utility,
.utility-pill.utility-pill,
.adoption-utility.adoption-utility,
.score-utility.score-utility {
  min-height: 53px !important;
  height: 53px !important;
  font-size: 14px !important;
}

.hz-utility.hz-utility :where(b, small, span, em, i, button, div, time),
.utility-pill.utility-pill :where(b, small, span, em, i, button, div, time),
.adoption-utility.adoption-utility :where(b, small, span, em, i, button, div, time),
.score-utility.score-utility :where(b, small, span, em, i, button, div, time) {
  font-size: 14px !important;
}

/* Las iniciales de los avatares que miran (AC, DB, PR) son la
   excepcion: van dentro de circulos de 26px y a 14px no entran.

   CORREGIDO. Estaban en 11px y rozaban el contenedor. La cuenta:
   el circulo mide 26 con borde de 1.6, o sea 22.8px utiles, y "AC"
   a 11px mide 16.5 -- quedaban 3.1px por lado. Y los circulos se
   pisan -6px entre si, asi que el borde del vecino entra sobre la
   letra.

   A 9px "AC" mide 13.5 y quedan 4.6px por lado. 9px es ademas el
   valor que tenian ANTES de esta hoja: la unificacion de la barra
   los habia subido a 11 sin necesidad. */
.hz-utility.hz-utility .hz-viewers > span,
.utility-pill.utility-pill .viewers > span,
.adoption-utility.adoption-utility .hz-viewers > span,
.score-utility.score-utility .hz-viewers > span {
  font-size: 9px !important;
}

/* ============================================================
   4 · EL AVATAR DEL PERFIL: 40px EN TODAS, CON FOTO
   ------------------------------------------------------------
   Convivian dos tamanos: 40px en las paginas sin hrzn-color.css y
   44px en las que si la cargan. El de 44 ademas DESBORDABA su
   tarjeta: la fila mide 56px con 8px de padding, o sea una caja
   interna de 40 -- el circulo de 44 se salia 4px por abajo.

   Se elige 40px justamente por eso: 8 + 40 + 8 = 56 cierra exacto
   en las paginas con hrzn-color, y en las otras la caja interna
   tambien es de 40. Un solo valor que encaja en las dos familias
   sin tocar la altura de la fila.

   La foto pasa a llenar el circulo. Venia a 54px dentro de un
   contenedor de 44 con overflow:hidden, o sea recortada y
   sobre-ampliada. Con 100% y object-fit:cover entra completa y
   encuadrada.

   Las iniciales quedan debajo como reserva: si la foto no carga,
   se ven; si carga, las tapa.
   ============================================================ */
.sidebar .profile-avatar {
  width: 40px !important;
  height: 40px !important;
  flex: 0 0 40px !important;
  display: grid !important;
  place-items: center !important;
  overflow: hidden !important;
  border-radius: 50% !important;
}

.sidebar .profile-avatar > img {
  grid-area: 1 / 1;
  width: 100% !important;
  height: 100% !important;
  object-fit: cover;
  display: block;
  /* El encuadre. La foto es cuadrada y el circulo tambien, asi que
     `cover` no recorta nada y se veia la foto entera -- hombros
     incluidos -- con la cara chica. El acercamiento se hace con
     transform, y el 4% hacia abajo es porque el centro de la cabeza
     cae sobre el 40% de la altura, no sobre el centro geometrico.

     El valor viene de hrzn-color.css, donde ya estaba: lo que se
     hace aca es extenderlo a las diez paginas. Antes existia solo
     en las cinco que cargan esa hoja, asi que en las otras cinco la
     misma foto se veia sin acercar. */
  transform: scale(1.22) translateY(4%);
}

.sidebar .profile-avatar > i {
  grid-area: 1 / 1;
  font-size: 13px !important;
  font-style: normal;
  font-weight: 700;
}

/* La columna de la tarjeta acompana al circulo. Y el chevron sale
   del grid en lugar de ocultarse: con display:none su columna de
   18px seguia reservada y el nombre no ganaba el sitio. */
/* Los dos textos del pie arrancan en la MISMA x, y el eje del
   circulo cae donde caen los otros iconos del rail.

   Habia que cumplir dos cosas a la vez, no una:

     texto en 72   -> 16 (borde del rail) + pad + avatar + gap = 72
     eje en 42     -> 16 + pad + avatar/2 = 42

   Con avatar de 40 eso se resuelve exacto con pad 6 y gap 10:

     avatar: izquierda 16+6 = 22, centro 22+20 = 42   OK
     texto:  22 + 40 + 10 = 72                        OK

   Y da lo mismo que la fila de arriba, que ya estaba en 72:

     support: 16 + pad 8 + slot 34 + gap 14 = 72

   Venia con pad 4 y gap 8, o sea 16+4+40+8 = 68: el nombre
   arrancaba 4px antes que "Help & Support". El comentario de
   hrzn-color.css afirmaba que los dos estaban en 72 y no era
   cierto -- ahora si lo es. */
.sidebar .profile-card {
  grid-template-columns: 40px minmax(0, 1fr) !important;
  padding-left: 6px !important;
  gap: 10px !important;
}
.sidebar .profile-card .chevron { display: none !important; }

/* La fila de Help & Support, con la misma cuenta.
   ------------------------------------------------------------
   Su geometria vivia en hrzn-color.css, que solo cargan cinco de las
   once paginas. Resultado medido: el texto arrancaba en 72 en esas
   cinco, en 67 en las otras cinco y en 65 en cloudbeach. Se trae aca
   para que las once usen la misma.

   Con el icono en 21px, las dos condiciones se resuelven asi:

     eje en 42    -> 16 + pad 8 + margen-izq 7.5 + 21/2 = 42
     texto en 72  -> 16 + 8 + 7.5 + 21 + margen-der 5.5 + gap 14 = 72

   Son los mismos numeros que ya tenian las cinco que funcionaban: no
   se invento una geometria nueva, se extendio la que estaba bien. */
.sidebar .support-link {
  padding-left: 8px !important;
  gap: 14px !important;
}
.sidebar .support-link svg {
  margin-left: 7.5px !important;
  margin-right: 5.5px !important;
}

/* ============================================================
   5 · LA BARRA DEJA DE PISAR EL TITULAR EN PANTALLAS ANGOSTAS
   ------------------------------------------------------------
   La barra es `position: absolute` arriba a la derecha y mide 780px
   FIJOS. El titular del hero ocupa hasta 798px. Asi que en cuanto
   el viewport no da para los dos, el texto se mete abajo de la
   barra.

   MEDIDO, sobre automations (el titular mas largo):

     viewport   izquierda de la barra   solape del texto
     1280px           414                    33px  X
     1366px           501                     0
     1440px           574                     0
     1920px          1054                     0

   Y en las otras seis paginas con barra: a 1366 ninguna choca; a
   1280 solo choca automations.

   El choque NO lo trajo la unificacion del titular: con los 66.56px
   originales el solape a 1318px era de 17px, y con 55px es de 28px.
   Ya estaba, la unificacion solo lo hizo un poco mas visible.

   El arreglo no invents nada: horizon-pages.css:1275 ya tiene el
   modo "barra en flujo" para pantallas angostas, solo que entraba a
   880px, muy por debajo de donde empieza el problema. Se sube el
   umbral y se aplica a los cuatro nombres de clase.

   UMBRAL RECALCULADO al bajar el titular a 40px. Suena al revés,
   pero con letra mas chica entran mas palabras por linea, asi que
   la PRIMERA linea se alarga y llega mas lejos hacia la barra. El
   texto del titular tiene un ancho tope fijo por pagina (966px en
   insights, 754px en automations) y la barra mide 663-780px, asi
   que conviven solo cuando el borde izquierdo de la barra pasa ese
   tope. MEDIDO:

     viewport   barra empieza en   insights      automations
     1440             740 / 574    choca +227    choca +180
     1600             900 / 734    choca  +67    choca  +20
     1800            1100 / 934    limpio        limpio
     1920 a 2400        mas a la derecha          limpio

   El umbral pasa a 1699px. Debajo de eso la barra ocupa su propia
   linea sobre el hero; a partir de 1700 flota como estaba pensada.

   El precio, que es real: entre 881 y 1699 -- o sea 1440, 1536 y
   1600, que son anchos de laptop muy comunes -- la barra deja de
   flotar. Se elige eso porque la alternativa era capar el titular a
   unos 540px de ancho, y a 40px eso lo parte en cinco o seis lineas.
   La barra mide 780px: sobre un main de 1083-1349 no hay sitio para
   los dos, y no es algo que se arregle afinando pixeles. */
@media (max-width: 1699px) {
  .hz-utility.hz-utility,
  .utility-pill.utility-pill,
  .adoption-utility.adoption-utility,
  .score-utility.score-utility {
    position: static !important;
    max-width: 100% !important;
    margin: 0 0 16px !important;
  }

  /* EXCEPCION: cloudbeach.
     Su hero es .hero-coast y tiene ALTO FIJO (221px), a diferencia de
     los otros, que crecen con el contenido. Pasar la barra a flujo la
     manda al final de .hero-copy, o sea justo sobre el borde inferior
     del hero y a todo el ancho -- medido, quedaba en top 215 con el
     hero terminando en 221.

     Ahi la barra se queda flotando. Puede hacerlo porque en esta
     pagina la separacion es VERTICAL y no horizontal: la barra ocupa
     y 24-77 y el titular arranca en 77, debajo. Horizontalmente si se
     cruzan -- el texto llega a x 811 y la barra empieza en 645 --,
     pero al estar en bandas distintas no se pisan.

     Es una separacion de 0px, o sea sin margen de error. Si el hero
     de cloudbeach cambia de alto o el titular pasa a dos lineas, esto
     se rompe y hay que resolverlo como en las otras. */
  .hero-coast .utility-pill.utility-pill {
    position: absolute !important;
    max-width: none !important;
    margin: 0 !important;
  }
}

/* ============================================================
   6 · LOS CUATRO CONTRASTES QUE RASPABAN
   ------------------------------------------------------------
   Quedaban cinco casos por debajo de 4.5:1. El de FinOps
   (.radar-axis-caption, 3.61) se arreglo en horizon-skin.css,
   porque vive dentro del iframe del cockpit y esa hoja si llega
   ahi. Los otros cuatro se resuelven aca.

   UN SOLO CRITERIO para los cinco:

     1. El alpha no se usa para tinta de texto. Sirve para
        rellenos y bordes, pero un color con alpha depende de lo
        que tenga debajo, asi que su contraste deja de ser una
        propiedad del token. Ese era el caso de FinOps.

     2. Donde el token correcto raspa, se baja UN escalon del
        MISMO matiz. Es el mismo movimiento que el sistema ya
        habia hecho con el ambar del hero (#A05F02 -> #8A5202,
        documentado en hrzn-scale.css).

   MEDIDO, con el fondo real apilado de cada uno:

     caso                        fondo      antes         ahora
     .hz-badge.is-warn           #F1ECE3    #A05F02 4.33  #8A5202 5.43
     .hz-badge.is-ok             #DCEDEB    #127A45 4.47  #0F6B3C 5.44
     .score-config-access span   #DCEBFA    #127A45 4.44  #0F6B3C 5.43
     .radar-axis-caption         #FFFFFF    alpha   3.61  opaco  10.24

   Los tres primeros quedan en 5.43 / 5.44 a proposito: es el
   mismo peso de contraste para los tres estados, asi que ninguno
   se lee mas fuerte que otro por accidente.

   El ambar #8A5202 ya existia en el sistema. El verde #0F6B3C es
   nuevo y es el equivalente exacto: un escalon mas oscuro que
   --h-ok-ink manteniendo el matiz. Sobre blanco da 6.5, asi que
   donde hoy el badge esta sobre tarjeta blanca tampoco pierde.
   ============================================================ */
.hz-badge.is-warn { color: #8A5202 !important; }
.hz-badge.is-ok { color: #0F6B3C !important; }
.score-config-access span { color: #0F6B3C !important; }

/* ============================================================
   7 · EL SALUDO: UN SOLO TAMANO
   ------------------------------------------------------------
   "Good morning, Alan" venia con cuatro tratamientos:

     18px / 500   automations, insights, settings, users, cockpit
     14.5px / 500 bridge-classic
     9.5px / 700  bridge
     16px / 400   cloudbeach

   Queda en 14.5px / 500 en las ocho. El peso tambien se unifica: sin
   eso seguirian leyendose distinto aunque midan igual.

   OJO en bridge: ahi el saludo funcionaba como copete chico de 9.5px
   arriba del titular. A 14.5 gana peso visual y la jerarquia del hero
   cambia. Es el precio de unificarlo y se pidio explicitamente.

   El del cockpit entra por la misma clase: se le agrego
   `hz-hero-greeting` al <p>, que solo tenia clases utilitarias y no
   habia forma de alcanzarlo sin un selector fragil. */
.hz-hero-greeting,
#bridge-greeting,
#greeting-title,
/* hrzn-scale.css:317 lo fija en 18px con
   `.hz-page.hz-page .hz-hero-greeting`, especificidad (0,3,0) y
   !important. Cargar esta hoja despues no alcanza contra (0,1,0):
   hay que igualar el selector. Se veia solo en automations y
   settings, que son las dos que cargan esa hoja. */
.hz-page.hz-page .hz-hero-greeting {
  font-size: 14.5px !important;
  font-weight: 500 !important;
}

/* ============================================================
   8 · EL TITULAR DEL COCKPIT DE FINOPS
   ------------------------------------------------------------
   FinOps no habia recibido NADA de la unificacion, y la razon es que
   su contenido no vive en finops.html: vive dentro del iframe de
   cockpit/app.html, que es otro documento y no cargaba esta hoja.
   Ya la carga.

   Su titular tenia el mismo defecto que el resto, con numeros
   distintos: MEDIDO 56.3px el importe contra 34.7px las palabras.

   Son tres <span> hermanos dentro de `.finops-hero .items-baseline`:
   el importe, los centavos y el texto. Los tres pasan a --t-hero.

   Los centavos pierden su tamano reducido de precio. Es deliberado:
   lo que se pidio es que el titular no distinga numero de letra, y
   los centavos son numero. */
.finops-hero .items-baseline > span {
  font-size: var(--t-hero) !important;
  font-weight: 800 !important;
  letter-spacing: -.015em !important;
  line-height: 1.05 !important;
}

/* ============================================================
   9 · EL COLOR DE LA TARJETA MANDA SOBRE SUS PROPIOS DATOS
   ------------------------------------------------------------
   Los datos coloreados de una tarjeta salian del color de OTRO
   estado. MEDIDO en adoption:

     tarjeta            dato                       estaba
     is-primary naranja delta "↑ 8.4%"             VERDE
     is-course azul     delta "↑ 3.4%"             VERDE
     is-good verde      barra de progreso          AZUL
     score-subject      barra de cobertura         VERDE en todas,
                        (is-watch = naranja)       tambien las naranjas

   La causa era la misma en los tres casos: un solo color fijo para
   el componente, sin mirar el estado. En adoption.css:121 el delta
   iba `color: var(--hz-ok-ink)` para TODAS las tarjetas.

   LO QUE NO SE TOCA, y es deliberado:

     · .adoption-distribution -- sus segmentos verde/naranja/rojo SON
       la distribucion. Igualarlos borra el dato.
     · el preview de bandas de score-config -- muestra justamente los
       tres colores de banda.
     · los estados por fila de .adoption-progress ("Needs attention",
       "Healthy") -- cada fila tiene su propio estado, no el del
       contenedor.

   O sea: manda el color de la tarjeta sobre los datos DE la tarjeta,
   no sobre componentes cuyo trabajo es codificar varios estados.

   Las team cards de adoption ya estaban bien: su barra
   (.adoption-team-card__score i) ya seguia el estado.
   ============================================================ */

:root {
  /* Claros de barra, derivados con la MISMA regla en las cuatro
     familias: +13 de luz sobre el base, matiz +4, saturacion al
     tope. Es la relacion que ya existia entre --hz-blue y --hz-sky.

       azul     #2450E4 L52 -> #58A9F4 L65   (tokens del sistema)
       naranja  #F97435 L59 -> #FFA36B L71
       verde    #1FA95C L39 -> #39D087 L52
       rojo     #E5484D L59 -> #F3807C L72

     El verde se atempero de s77 a s62: su base es mas oscura que las
     otras (L39), asi que la formula pura daba un mint neon fuera de
     la paleta. */
  --u-ok-lite: #39D087;
  --u-bad-lite: #F3807C;
  --u-orange-lite: #FFA36B;

  /* Tintes de tarjeta. Existen como --hz-card-*-bg en
     horizon-2050-shell.css, pero esa hoja la cargan solo cuatro
     paginas. Se redefinen aca para que insights, automations y
     bridge-classic tambien puedan usarlos. */
  /* SUBIDA DE INTENSIDAD. Los valores anteriores (.11 a .13 de radial y
     una base casi blanca: #F2FBF6, #FFF8F1, #FFF7F5) no llegaban a
     leerse contra el fondo #E8EEF9: el naranja se veia gris calido y el
     verde no se distinguia de una tarjeta neutra. Ahora el radial va a
     .20-.22 y la base del lineal baja tres pasos. El matiz es el mismo
     de siempre -- --hz-ok, --hz-orange, --hz-bad, --hz-blue -- asi que
     no cambia el color, cambia cuanto se ve.

     El azul es nuevo: es el tinte de las tarjetas SIN estado, que antes
     quedaban blancas y no se leian como parte de la fila. */
  --u-tint-blue: radial-gradient(circle at 92% 0, rgba(36,80,228,.20), transparent 42%), linear-gradient(145deg,#E7EEFD,#fff 72%);
  --u-tint-green: radial-gradient(circle at 92% 0, rgba(31,169,92,.20), transparent 42%), linear-gradient(145deg,#E3F6EC,#fff 72%);
  --u-tint-orange: radial-gradient(circle at 92% 0, rgba(249,116,53,.22), transparent 42%), linear-gradient(145deg,#FFEBDD,#fff 72%);
  --u-tint-red: radial-gradient(circle at 92% 0, rgba(229,72,77,.20), transparent 42%), linear-gradient(145deg,#FFE7E6,#fff 72%);
}

/* ---- A · las tarjetas KPI de adoption ---------------------------- */

.adoption-kpi.is-good p b { color: var(--hz-ok-ink) !important; }
.adoption-kpi.is-course p b { color: var(--hz-blue) !important; }
.adoption-kpi.is-primary p b { color: #B85B08 !important; }

.adoption-kpi.is-good footer span {
  background: linear-gradient(90deg, var(--hz-ok), var(--u-ok-lite)) !important;
}
.adoption-kpi.is-course footer span {
  background: linear-gradient(90deg, var(--hz-blue), var(--hz-sky)) !important;
}

/* ---- B · la cobertura de score-subject --------------------------- */

/* Los tintes reales de esta familia: is-watch y is-medium = naranja,
   is-building = azul. Aqui decia que is-medium era AZUL "medido y no
   supuesto"; la medicion era buena y la conclusion no. Lo que estaba
   azul no era is-medium: era .is-selected repintando fondo y borde de
   la unica tarjeta is-medium de la pantalla. Su regla de tinte en
   score.css siempre agrupo is-medium con is-watch en naranja. */
.score-subject.is-watch .score-coverage i,
.score-subject.is-medium .score-coverage i { background: var(--hz-orange) !important; }

/* is-building no tenia tinte: es una de las tarjetas que debian
   tener color y no lo tenian. Va en azul -- todavia esta juntando
   datos, no es un estado de salud. */
.score-subject.is-building {
  background: var(--hz-card-blue-bg, radial-gradient(circle at 92% 0, rgba(8,100,238,.12), transparent 36%), linear-gradient(145deg,#F3F8FF,#fff 64%)) !important;
  border-color: rgba(8,100,238,.42) !important;
}
.score-subject.is-building .score-coverage i { background: var(--hz-blue) !important; }

/* El estado manda sobre el tinte, tambien en oscuro. */
[data-theme="dark"] .score-subject.is-medium,
[data-theme="dark"] .score-subject.is-watch {
  border-color: var(--hz-card-orange-border) !important;
  background: var(--hz-card-orange-bg) !important;
}
[data-theme="dark"] .score-subject.is-selected {
  box-shadow: none !important;
}
[data-theme="dark"] .score-subject__button:hover {
  background: transparent !important;
}
[data-theme="dark"] .score-page .score-subject:hover {
  box-shadow: inset 4px 0 var(--score-edge) !important;
}

/* ---- C · tarjetas-fila que no tenian color --------------------- */
/* Tenian estado adentro y ningun tinte que lo acompanara. El estado
   vive en un hijo (.hz-state.is-*), no en la fila, asi que se lee con
   :has() en lugar de agregar clases al markup de cinco archivos. */

/* En insights el marcador NO es .hz-state: dos de las seis filas lo
   traen sin clase de estado ("Efficiency" y "ROI · correlation"), y
   quien si lleva el estado en las seis es .ins-impact. Con
   .hz-state esas dos quedaban sin tinte -- medido. En .cv-row de
   bridge-classic el estado si vive en .hz-state. */
.ins:has(.ins-impact.is-warn),
.cv-row:has(.hz-state.is-warn) {
  background: var(--u-tint-orange) !important;
  border-color: rgba(249,116,53,.42) !important;
}
.ins:has(.ins-impact.is-bad),
.cv-row:has(.hz-state.is-bad) {
  background: var(--u-tint-red) !important;
  border-color: rgba(229,72,77,.42) !important;
}
.ins:has(.ins-impact.is-ok),
.cv-row:has(.hz-state.is-ok) {
  background: var(--u-tint-green) !important;
  border-color: rgba(31,169,92,.42) !important;
}

/* Las reglas de automations si tienen su estado en la propia fila:
   por defecto activa, mas is-paused e is-broken. */
.rule:not(.is-paused):not(.is-broken) {
  background: var(--u-tint-green) !important;
  border-color: rgba(31,169,92,.42) !important;
}
.rule.is-broken {
  background: var(--u-tint-red) !important;
  border-color: rgba(229,72,77,.42) !important;
}
/* is-paused se queda neutra a proposito: pausada no es un estado de
   salud, es ausencia de actividad. Pintarla de un color le daria un
   significado que no tiene. */

/* ============================================================
   HRZN · EL FONDO DEL PRODUCTO, UNO SOLO
   ------------------------------------------------------------
   Habia tres fondos distintos y ninguno separaba de la tarjeta:

     #F1F5FB  Users, Insights, Automations, Settings, el cockpit
     #F4F7FB  AI Adoption, AI Score, AI Score Settings
     #F4F6FC  el shell (--page de hrzn-color.css)

   El peor problema no era la falta de unidad sino el contraste:
   #F1F5FB contra la tarjeta blanca da 1.09:1. La tarjeta no
   flotaba, la dibujaba el borde.

   Ahora es #E8EEF9 en todas: 1.157:1 contra el blanco, 70% mas de
   separacion. El techo lo pone --hz-sunken (#EAF0FB, 1.144:1), que
   es el gris azulado de las pistas de barra, los hovers y las
   bandejas: el fondo tiene que quedar CLARO como el, no mas oscuro,
   o toda pista de barra dentro de una tarjeta se hunde de mas. Por
   eso #E8EEF9 y no un azul mas profundo -- para bajar mas hay que
   mover primero el sunken, y eso toca pistas, hovers y segmentos en
   todo el producto.

   Va en esta hoja y no en las siete que pintan fondo porque es
   la unica que cargan LAS ONCE paginas y tambien cockpit/app.html,
   adentro del iframe. Un solo lugar auditable.

   La guarda :not([data-theme="dark"]) no es opcional: horizon-dark.css
   se enlaza ANTES que esta hoja, asi que sin ella este literal le
   pisaria el canvas nocturno al tema oscuro.
   ============================================================ */

:root:not([data-theme="dark"]) { --hz-canvas: #E8EEF9; }

/* body: las paginas del kit ya pintan var(--hz-canvas). El shell
   pintaba body.bridge-page con --hz-sunken, que es un token de
   hundido y no de lienzo. */
html:not([data-theme="dark"]) body,
html:not([data-theme="dark"]) body.bridge-page { background: var(--hz-canvas); }

/* las tres pantallas de IA pintan su propio main con un literal, y
   el cockpit hereda el suyo de una utilidad de Tailwind
   (bg-slate-100/70) que ninguna hoja remapeaba. */
html:not([data-theme="dark"]) .adoption-main,
html:not([data-theme="dark"]) .score-main,
html:not([data-theme="dark"]) .score-config-main,
html:not([data-theme="dark"]) .finops-dashboard { background-color: var(--hz-canvas); }

/* cloudbeach.html es la unica con .dashboard-content: conserva su
   resplandor radial y cambia solo el color de base. */
html:not([data-theme="dark"]) .dashboard-content {
  background: radial-gradient(circle at 15% 15%, rgba(214, 231, 248, .35), transparent 30%), var(--hz-canvas);
}

/* ============================================================
   HRZN . UN SOLO SISTEMA DE COLOR DE TARJETA
   ------------------------------------------------------------
   Habia CUATRO recetas de tinte conviviendo:

     .hz-kpi.is-*        lineal al 12% sobre blanco   (el kit)
     --u-tint-*          radial 11-13% + lineal       (las filas)
     --hz-card-*-bg      radial 12% + lineal          (las de IA)
     .finops-kpi--*      lineal al 5%                 (el cockpit)

   Ahora hay una: --u-tint-*. Las otras tres se redefinen contra ella,
   asi que una tarjeta verde se ve igual en Settings, en Insights, en
   AI Adoption y en el cockpit.

   Y el color pasa a ser obligatorio: toda tarjeta lleva tinte. Si no
   reporta salud, lleva el azul. Antes las neutras quedaban blancas y
   rompian la fila -- Alerts en Settings, Runs y Saved en Automations,
   Captured y Monitored en Insights.

   El estado no siempre esta en la tarjeta: en varias familias vive en
   un hijo (.hz-kpi-delta.is-*, .hz-badge.is-*). Se lee con :has() en
   lugar de agregar clases al markup de cinco archivos.
   ============================================================ */

/* ---- 1 . el kit: toda tarjeta con color, el azul como piso ------- */

.hz-kpi { background: var(--u-tint-blue) !important; --u-rail: var(--hz-blue); }
.hz-kpi.is-lead { background: var(--u-tint-blue) !important; --u-rail: var(--hz-blue); }
.hz-kpi.is-ok,
.hz-kpi:has(.hz-kpi-delta.is-ok),
.hz-kpi:has(.hz-badge.is-ok) { background: var(--u-tint-green) !important; --u-rail: var(--hz-ok); }
.hz-kpi.is-warn,
.hz-kpi:has(.hz-kpi-delta.is-warn),
.hz-kpi:has(.hz-badge.is-warn) { background: var(--u-tint-orange) !important; --u-rail: var(--hz-orange); }
.hz-kpi.is-bad,
.hz-kpi:has(.hz-kpi-delta.is-bad),
.hz-kpi:has(.hz-badge.is-bad) { background: var(--u-tint-red) !important; --u-rail: var(--hz-bad); }

/* ---- 2 . la familia de IA apunta a los mismos tintes ------------- */

:root:not([data-theme="dark"]) {
  --hz-card-blue-bg: var(--u-tint-blue);
  --hz-card-green-bg: var(--u-tint-green);
  --hz-card-orange-bg: var(--u-tint-orange);
  --hz-card-red-bg: var(--u-tint-red);
}

/* ---- 3 . el cockpit de FinOps: que parezcan tarjetas ------------- */
/* Los KPI del cockpit venian con un lineal al 5% y sin cromo propio:
   se leian como bloques de fondo, no como tarjetas. Reciben el mismo
   tinte que el resto del producto, mas borde, radio y sombra de dos
   capas. Los que no reportan salud (spend, budget) van en azul. */

html:not([data-theme="dark"]) .finops-dashboard .finops-kpi {
  background: var(--u-tint-blue) !important;
  border: 1px solid var(--hz-line) !important;
  border-radius: var(--hz-r-card) !important;
  box-shadow: 0 1px 2px rgba(10, 30, 70, .06), 0 6px 16px -6px rgba(10, 30, 70, .18) !important;
  --u-rail: var(--hz-blue);
}
html:not([data-theme="dark"]) .finops-dashboard .finops-kpi--projected {
  background: var(--u-tint-red) !important;
  --u-rail: var(--hz-bad);
}
html:not([data-theme="dark"]) .finops-dashboard .finops-kpi--watch {
  background: var(--u-tint-orange) !important;
  --u-rail: var(--hz-orange);
}

/* Systems Load: las tres categorias ya eran tarjetas de estado -- su
   barra lo dice -- pero la superficie era la misma para las tres. */
html:not([data-theme="dark"]) .finops-dashboard .systems-load-card {
  background: var(--u-tint-green) !important;
  border-radius: var(--hz-r-card) !important;
  box-shadow: 0 1px 2px rgba(10, 30, 70, .06), 0 6px 16px -6px rgba(10, 30, 70, .18) !important;
  --u-rail: var(--hz-ok);
}
html:not([data-theme="dark"]) .finops-dashboard .systems-load-card.is-warn {
  background: var(--u-tint-orange) !important;
  --u-rail: var(--hz-orange);
}
html:not([data-theme="dark"]) .finops-dashboard .systems-load-card.is-bad {
  background: var(--u-tint-red) !important;
  --u-rail: var(--hz-bad);
}

/* ---- 4 . el filo lateral: fuera en reposo, solo en hover -------- */
/* El filo de 4px marcaba el estado de forma permanente y competia con
   el tinte, que ya lo dice. Se lo queda el hover, donde ademas hace
   falta: es la senal de que la tarjeta responde al cursor.

   En hover va como box-shadow inset y NO como border, para que la caja
   no se mueva: un border de 4px le come 3px de ancho al contenido y el
   texto salta al pasar el mouse. El color sale de --u-rail, que cada
   estado define aca. */

.hz-kpi.is-ok, .hz-kpi.is-warn, .hz-kpi.is-bad,
.ins.is-focal, .rule.is-broken,
.adoption-kpi.is-primary, .adoption-attention,
.adoption-team-card, .adoption-team-card.is-medium, .adoption-team-card.is-low,
.score-recipe-rules article, .score-measurement-budgets article,
.score-profile-grid article, .score-validation-panel, .score-objective-guidance,
.score-wizard-layout > aside, .score-objective-old-new article,
.score-objective-old-new label, .score-config-warning {
  border-left-width: 1px !important;
}

/* los tintes de las filas tambien definen su riel */
.ins:has(.ins-impact.is-warn), .cv-row:has(.hz-state.is-warn) { --u-rail: var(--hz-orange); }
.ins:has(.ins-impact.is-bad), .cv-row:has(.hz-state.is-bad) { --u-rail: var(--hz-bad); }
.ins:has(.ins-impact.is-ok), .cv-row:has(.hz-state.is-ok) { --u-rail: var(--hz-ok); }
.rule:not(.is-paused):not(.is-broken) { --u-rail: var(--hz-ok); }
.rule.is-broken { --u-rail: var(--hz-bad); }

/* La regla pausada tambien lleva color, y va en azul. Mas arriba en
   esta hoja hay una nota que la dejaba neutra a proposito -- que
   pausada no es un estado de salud. Es cierto, y por eso NO va en
   verde ni en rojo: va en el azul de las tarjetas sin estado, que es
   justo lo que es. Blanca era la unica fila que se salia de la lista. */
.rule.is-paused { background: var(--u-tint-blue) !important; --u-rail: var(--hz-blue); }
.adoption-team-card { --u-rail: var(--hz-ok); }
.adoption-team-card.is-medium { --u-rail: var(--hz-orange); }
.adoption-team-card.is-low { --u-rail: var(--hz-bad); }
.adoption-attention { --u-rail: var(--hz-bad); }
.adoption-kpi.is-primary { --u-rail: var(--hz-orange); }
.adoption-kpi.is-good { --u-rail: var(--hz-ok); }
.adoption-kpi.is-course { --u-rail: var(--hz-blue); }

/* ---- 5 . el icono de la fila toma el color de su estado --------
   Las cajas de icono de las filas -- .cv-ico en el dashboard Classic y
   .rule-ic en Automations -- estaban clavadas en --hz-blue sobre
   --hz-sunken. En una fila naranja o roja el icono seguia azul: era el
   unico elemento de la fila que no acompanaba al estado, con la
   insignia, el filo y la cifra ya en su color.

   Automations ya tenia esto resuelto a mano para un solo caso
   (.rule.is-broken .rule-ic, el rojo de la regla desconectada). Esto
   lo generaliza a todos los estados y a las dos paginas, y esa
   excepcion se borra de automations.html por quedar redundante.

   El color sale de --u-rail, el mismo token que alimenta el filo
   izquierdo del hover: una sola fuente para el color de estado de la
   fila, asi el icono no puede desincronizarse del riel. El fondo de la
   caja lo acompana al 10%, el mismo alfa que usaba la excepcion.

   El background va declarado dos veces a proposito: color-mix() no se
   usa en ninguna otra parte de este proyecto, asi que la primera linea
   deja el --hz-sunken de siempre para el navegador que no lo soporte.
   (:has() si se usa, 20 veces en esta misma hoja, y tiene soporte
   equivalente -- pero el respaldo no cuesta nada.)

   Va SOLO en filas. Las tarjetas quedan afuera a proposito: ahi el
   icono convive con insignia, velo, filo y barra, y un gesto de color
   mas satura. */
.cv-row .cv-ico,
.rule .rule-ic {
  color: var(--u-rail, var(--hz-blue));
  background: var(--hz-sunken);
  background: color-mix(in srgb, var(--u-rail, var(--hz-blue)) 10%, transparent);
}

/* La tarjeta seleccionada lleva el mismo filo izquierdo que el hover, y
   nada mas: el tinte de estado se queda donde esta. Va con la sombra de
   reposo y no con la de hover -- la tarjeta esta elegida, no levantada.

   Deliberadamente ANTES del bloque de hover: misma especificidad y los
   dos !important, asi que decide el orden. Al ir primero, pasar el
   cursor por encima de la tarjeta ya seleccionada la levanta igual que
   a las demas. */
.adoption-team-card.is-highlighted {
  box-shadow: inset 4px 0 var(--u-rail, var(--hz-blue)), var(--hz-card-state-shadow) !important;
}

.hz-kpi:hover, .ins:hover, .rule:hover,
.adoption-kpi:hover, .adoption-attention:hover, .adoption-team-card:hover,
.score-recipe-rules article:hover, .score-measurement-budgets article:hover,
.score-profile-grid article:hover,
html:not([data-theme="dark"]) .finops-dashboard .finops-kpi:hover,
html:not([data-theme="dark"]) .finops-dashboard .systems-load-card:hover {
  box-shadow: inset 4px 0 var(--u-rail, var(--hz-blue)), var(--hz-sh-soft) !important;
}

/* ---- 6 . lo que todavia le sumaba color a Systems Load ----------
   El tinte de las tres tarjetas de Systems Load ya era el mismo
   --u-tint-* que el de los KPI del cockpit (seccion 3): medido, las
   dos filas resuelven al mismo radial .20 + lineal 145deg. Lo que
   hacia que la fila se leyera con MAS color que el resto no era la
   tarjeta, era la bandeja: horizon-skin.css pinta el contenedor de
   las tres con var(--hz-sunken) -- ese celeste rgb(234,240,251) que
   se ve detras -- y ninguna otra fila de tarjetas del producto se
   apoya sobre una bandeja pintada. Los KPI del cockpit van directo
   sobre el canvas. Se le saca el fondo a la bandeja, no a la tarjeta:
   el tinte de estado es justamente lo que hay que conservar.

   Solo en claro: el hundido de oscuro lo maneja horizon-dark.css. */
html:not([data-theme="dark"]) .finops-dashboard .systems-load-panel > .grid {
  background: transparent !important;
}

/* ---- 7 . las dos ultimas tarjetas fuera del sistema -------------
   Barrido de las 11 pantallas: todas las tarjetas pintadas resuelven
   a --u-tint-*, menos estas dos, que se quedaron con la receta vieja
   del lineal al 5-7% sobre blanco. Se ven mas lavadas que sus vecinas
   y rompen la fila.

     .projection-card              cloudbeach.css, lineal 130deg #fff8f7
     .chartplotter-course          hrzn-color.css, lineal 135deg 7%
       .is-drifting

   Las dos reportan lo mismo -- proyeccion por encima del presupuesto --
   asi que van al tinte que ya usa .finops-kpi--projected. */
html:not([data-theme="dark"]) .projection-card {
  background: var(--u-tint-red) !important;
  --u-rail: var(--hz-bad);
}
html:not([data-theme="dark"]) .finops-dashboard .chartplotter-course.is-drifting {
  background: var(--u-tint-orange) !important;
  --u-rail: var(--hz-orange);
}

/* ---- 8 . el panel de Score: un solo color por vez ----------------
   .score-breakdown ya toma el color del estado del reading: verde por
   defecto y naranja/rojo/gris con .is-watch/.is-bad/.is-unknown, que
   js/score.js le pone segun a quien elijas en la tabla. Ese verde dice
   algo y se queda.

   Lo que metia el segundo color eran tres bloques de adentro, que
   traian azul propio sin que ese azul significara nada:

     .score-formula          var(--hz-sunken) = #EAF0FB, el mismo
                             celeste de bandeja de la seccion 6
     .score-counterfactual   fondo #F7FAFE y filo izquierdo --hz-blue
     .score-component-detail --hz-card-green-bg FIJO: se quedaba verde
                             aunque el panel pasara a naranja o rojo,
                             que es el caso peor -- dos estados a la
                             vez en la misma tarjeta

   Pasan a blanco translucido: siguen leyendose como bloques aparte,
   pero toman el matiz del panel en vez de importar uno. El filo del
   counterfactual pasa a --u-rail, el riel de estado que ya usa la
   seccion 4, asi acompana al panel en lugar de contradecirlo.

   El boton se queda azul a proposito: es la accion primaria y el azul
   es el color de accion de todo el producto, no un estado. En verde
   leeria como confirmacion de algo.

   .is-absent no se toca: su gris neutro es la senal de que el
   componente no se pudo medir. */
html:not([data-theme="dark"]) .score-breakdown { --u-rail: var(--hz-ok); }
html:not([data-theme="dark"]) .score-breakdown.is-watch { --u-rail: var(--hz-orange); }
html:not([data-theme="dark"]) .score-breakdown.is-bad { --u-rail: var(--hz-bad); }
html:not([data-theme="dark"]) .score-breakdown.is-unknown { --u-rail: #7B879D; }

html:not([data-theme="dark"]) .score-breakdown .score-formula,
html:not([data-theme="dark"]) .score-breakdown .score-counterfactual,
html:not([data-theme="dark"]) .score-breakdown .score-component-detail:not(.is-absent) {
  background: rgba(255, 255, 255, .72) !important;
}
html:not([data-theme="dark"]) .score-breakdown .score-component-detail:not(.is-absent) {
  border-color: rgba(10, 30, 70, .10) !important;
}
html:not([data-theme="dark"]) .score-breakdown .score-counterfactual {
  border-left-color: var(--u-rail) !important;
}
