/* ============================================================
   HRZN · SISTEMA DE COLOR
   Unifica el color del cockpit de FinOps sobre la paleta de marca.
   ------------------------------------------------------------
   Archivo propio, como hrzn-type.css, y por la misma razon: la
   version anterior de este trabajo vivia dentro de horizon-skin.css
   y desaparecio cuando esa hoja se regenero.

   QUE ENCONTRE (medido en la pagina en vivo, 94 colores distintos):

   Hay DOS sistemas de tokens corriendo en paralelo:

     a) --hz-ink #0A1E46 · --hz-blue #2450E4 · --hz-orange #F97435
        --hz-sky #58A9F4 · --hz-line #DCE4F5
        + --hz-ok #1FA95C · --hz-warn #F59E0B · --hz-bad #E5484D
        + rampa de texto secundario --hz-ink-2/3/4 (navy, no gris)
        = la paleta de marca, correcta, y SI en uso en horizon-skin.css.
        (Una version anterior de este comentario decia que tenia cero
        usos. Era falso: lo deduje de un grep sobre el CSSOM que fallaba
        en silencio porque Tailwind v4 mete sus reglas en @layer y no se
        enumeran. El grep sobre el CSS crudo lo desmintio.)

     b) --ink #071f49 · --navy #082d5d · --blue #0864ee
        --orange #ff681c  (cloudbeach.css)
        + la escala de Tailwind v4 en index.css
        = lo que el producto pinta de verdad.

   EL BUG REAL no era que faltaran los tokens: era que las escalas de
   Tailwind NO coincidian con ellos. El mismo estado semantico se
   pintaba de dos colores distintos segun si venia de una regla --hz-*
   o de una utilidad de Tailwind:

     Danger de marca  #E5484D   vs   rose-500  #f1392f    dE 18.7
     Success de marca #1FA95C   vs   emerald-500 #12a06d  dE 14.4

   Por eso se veian "rojos que no son del manual" al lado de los
   correctos. El resto del sistema (b) tambien estaba fuera de marca:

     azul de accion  #0864ee -> #2450E4   dE 11.9
     naranja         #ff681c -> #F97435   dE 11.4
     sky-300         #8fb4f8 -> #58A9F4   dE 11.4
     sky-400         #4f8cf0 -> #58A9F4   dE 20.0
     navy            #082d5d -> #0A1E46   dE  8.3
     ink             #071f49 -> #0A1E46   dE  1.4  (este ya estaba bien)

   EL MECANISMO: Tailwind v4 genera las utilidades como
   `.text-slate-900{color:var(--color-slate-900)}`. Redefinir esas
   variables retunea 155 utilidades de golpe, sin pelear selectores.
   Las variantes con opacidad son la excepcion: inlinean el hex
   (`.border-slate-200\/60{border-color:#d9e3f099}`), asi que esas van
   parcheadas a mano mas abajo — son 27 en toda la pagina.

   Se enlaza ULTIMO, despues de horizon-dark.css.
   ============================================================ */

/* ---- 1 · ANCLAS SEMANTICAS ------------------------------------
   El nombre dice la funcion, no el matiz. Un token llamado --hz-blue
   no se puede reasignar sin mentir; uno llamado --h-action si. */
:root {
  --h-action:     #2450E4;   /* azul de identidad · 6.28:1 sobre blanco */
  --h-ink:        #0A1E46;   /* texto y superficies profundas */
  /* NARANJA DE NO-ESTADO. Decision de Dario: el naranja del sitio,
     #F05A28, no el #F97435 del manual (estan a dE 10.2). Su trabajo es
     lo que NO es salud: el extremo calido del degradado de trayectoria,
     los acentos del grafico, la marca del insight accionable.

     Medido, y es la razon de que existan dos tokens y no uno:
       #F05A28 como texto sobre blanco = 3.39:1 -> NO cumple AA
       se distingue de los tres estados: dE 25 del Danger (el mas
       cercano), 40 del Warning, 111 del Success
     Asi que el vivo RELLENA y el -ink se LEE. El -ink sale de oscurecer
     el propio #F05A28 al 84%: mismo tono, 4.65:1, y a dE 17.5 del
     Danger-ink, o sea que un texto naranja no se confunde con uno rojo. */
  --h-accent:     #F05A28;   /* SOLO RELLENO · 3.39:1 */
  --h-accent-ink: #B84018;   /* naranja legible · 5.53:1 en blanco,
                                4.99:1 sobre la pildora #FFF0ED */
  --h-sky:        #58A9F4;   /* azul de apoyo y foco */

  /* estados · valores del manual de marca, no derivados de la escala
     que ya habia en el codigo. La primera version de este archivo puso
     #12A06D y #F1392F, que salian de las escalas emerald/rose de
     index.css y estaban a dE 14.4 y dE 18.7 del valor real. Corregido.

     El manual dice: "Estado (dot+label+color, NUNCA color solo)".
     Ahora se entiende por que — medido sobre blanco, NINGUNO de los
     tres sirve como texto:
         Success #1FA95C  3.05:1
         Warning #F59E0B  2.15:1
         Danger  #EE0033  4.48:1
     El color es el punto y el relleno; la etiqueta lleva el
     significado. Para texto van las variantes -ink, que son el MISMO
     valor de marca oscurecido — mismo tono, contraste legal. */
  --h-ok:    #1FA95C;  --h-ok-ink:   #127A45;  /* Success · 5.4:1 */
  --h-warn:  #F59E0B;  --h-warn-ink: #A05F02;  /* Warning · 5.08:1 en blanco */
  /* NOTA MEDIDA, sin cambio de token.

     Esta guia razona contra BLANCO, y el hero no lo es: es un lavado
     celeste #DCE9FB sobre el video. Sobre ese fondo, de nuestros tres
     estados el rojo aguanta (4.74) y el ambar NO: 4.14 contra un
     minimo de 4.5. El verde no aparece en ningun hero.

     El valor que si pasa en las tres superficies es #8A5202 -- mismo
     matiz 35.3, solo un escalon mas oscuro:

                    blanco   lavado   su tinte al 12%
       #A05F02       5.08     4.14 X    4.63
       #8A5202       6.39     5.20      5.82

     Se decidio NO mover el token global: FinOps usa este ambar en la
     tabla de budgets, el radar y Systems Load, y cambiarlo con otra
     persona trabajando en el mismo deploy es mas riesgo que beneficio.
     El arreglo va scopeado a Settings en hrzn-scale.css, redefiniendo
     --hz-warn-ink bajo #settingsMain.

     Si algun dia se generaliza, es mover esta linea y borrar el scope
     -- y entonces el #8A5202 que horizon-pages.css tiene escrito a
     mano como excepcion del hero deja de ser excepcion. */
  /* Danger, subido de vibracion por pedido. Medido, y elegido entre
     siete candidatos porque las tres cosas mejoran a la vez:
       croma      68.6 -> 88.1  (+28% de vibracion)
       contraste  3.91 -> 4.48:1
       dE vs el naranja de no-estado  25.1 -> 26.3
     O sea que ademas de mas furioso, se distingue MEJOR del naranja
     que el anterior — que era el riesgo real de subirle saturacion. */
  --h-bad:   #EE0033;  --h-bad-on-navy: #FF7285;  /* rojo de estado sobre la barra navy · 4.72:1 */
  --h-bad-ink:  #CC002B;  /* Danger · 5.83:1 */

  /* serie 2 de data-viz · el manual la lista y en el codigo no existia */
  --h-teal: #0FA3A3;
  --h-grid: #E4EAF7;

  --h-surface: #FFFFFF;
  --h-canvas:  #F4F6FC;
  --h-sunken:  #EAF0FB;
  --h-border:  #DCE4F5;
}

/* ---- 2 · ESCALA TAILWIND RE-ANCLADA --------------------------
   Va sin acotar por tema a proposito: la identidad de color no
   depende de si el usuario esta en claro u oscuro. El naranja de
   marca es el mismo naranja en los dos.

   sky queda anclada en tres valores de marca — 400 = sky,
   600 = action, 900 = ink — y los pasos intermedios interpolan.
   Asi cualquier utilidad sky-* cae dentro de la identidad. */
:root {
  --color-sky-50:  #EFF4FE;
  --color-sky-100: #DCE8FD;
  --color-sky-200: #BBD4FA;
  --color-sky-300: #8CBEF7;
  --color-sky-400: #58A9F4;   /* marca · sky */
  --color-sky-500: #3B7DEC;
  --color-sky-600: #2450E4;   /* marca · action */
  --color-sky-700: #1D40B8;
  --color-sky-800: #16318C;
  --color-sky-900: #0A1E46;   /* marca · ink */

  /* cinco familias distintas colapsadas al mismo valor: el proyecto
     ya las habia unificado, solo que al valor equivocado */
  --color-blue-600:   #2450E4;
  --color-indigo-600: #2450E4;
  --color-purple-600: #2450E4;
  --color-violet-600: #2450E4;
  --color-violet-500: #3B7DEC;
  --color-violet-700: #1D40B8;

  /* neutros: solo dos cambios, los dos de bajo riesgo.
     El resto de la rampa ya era coherente y no se toca. */
  --color-slate-200: #DCE4F5;   /* era #d9e3f0 · pasa a ser el borde de marca */
  --color-slate-900: #0A1E46;   /* era #071f49 · dE 1.4 · 704 usos en la pagina */

  /* AMBER = ADVERTENCIA, no acento.
     La escala "amber" de este proyecto era naranja (amber-500 = #ff681c),
     el mismo tono que el acento de marca. Mi primera version la ancle en
     el acento #F97435 e invente los pasos intermedios (#FA8548, #DE5A1B),
     que no salen de ningun manual. Ese era el "naranja viejo" que seguia
     apareciendo.

     Corregido: amber se ancla en el WARNING de marca #F59E0B, que es lo
     que la escala significa en cualquier sistema de diseno. El acento
     #F97435 queda reservado a --h-accent y NO se reparte por una escala
     de utilidades, porque el manual lo limita a "insight que amerita
     accion", exactamente 1 por pantalla (regla 25/5/1). */
  --color-amber-50:  #FEF6E7;
  --color-amber-100: #FDE8BE;
  --color-amber-200: #FBD78C;
  --color-amber-300: #F9C55A;
  --color-amber-400: #F7B32F;
  --color-amber-500: #F59E0B;   /* marca · Warning */
  --color-amber-600: #C67F08;   /* paso intermedio, no de manual */
  --color-amber-700: #A05F02;   /* = --hz-warn-ink · 5.08:1 en blanco */
  --color-amber-800: #7A4F05;

  /* EMERALD = SUCCESS · anclada en #1FA95C.
     Estaba a dE 10.8-14.4 del estado de marca y por eso el verde de la
     pantalla no era el verde de la marca. */
  --color-emerald-50:  #E9F8F0;
  --color-emerald-100: #C8EEDB;
  --color-emerald-200: #99DEBC;
  --color-emerald-300: #5FC894;
  --color-emerald-400: #35B673;
  --color-emerald-500: #1FA95C;   /* marca · Success */
  --color-emerald-600: #127A45;   /* = --hz-ok-ink · 5.4:1 */
  --color-emerald-700: #0F5F35;
  --color-emerald-800: #0F512C;

  /* ROSE = DANGER · anclada en #E5484D.
     Toda la escala estaba a dE 18.7 del estado de marca — este era el
     "rojo que no esta en el manual". */
  --color-rose-50:  #FDE9EC;
  --color-rose-100: #FBCBD3;
  --color-rose-200: #F79AA9;
  --color-rose-300: #F4657F;
  --color-rose-400: #F13A5B;
  --color-rose-500: #EE0033;   /* Danger vibrante */
  --color-rose-600: #CC002B;   /* = --h-bad-ink · 5.83:1 */
  --color-rose-700: #A80024;
  --color-rose-800: #85001C;

  /* serie 2 de data-viz · el teal del manual no existia en el codigo.
     Queda definido y sin usos: su lugar son las series de los graficos,
     no los iconos de categoria (ver seccion 13). */
  --color-teal-500: #0FA3A3;
}

/* ---- 3 · SISTEMA HEREDADO DE cloudbeach.css ------------------
   Estas si van acotadas a claro: horizon-dark.css redefine --ink
   como #EAF2FF (texto claro sobre fondo oscuro), o sea que --ink
   significa "color de texto" y depende del tema. Pisarlo sin acotar
   romperia el modo oscuro — que es exactamente el error que ya
   cometi una vez en este proyecto. */
:root:not([data-theme="dark"]) {
  --ink:    #0A1E46;   /* era #071f49 */
  --navy:   #0A2C5E;   /* era #082d5d · mismo claro, tono alineado al ink */
  --blue:   #2450E4;   /* era #0864ee · el cambio de identidad mas grande */
  --blue-2: #58A9F4;   /* era #2b8bff */
  --sky:    #D7E8FD;   /* era #cbe6ff */
  --line:   #DCE4F5;   /* era #d9e3f0 */
  --orange: #F97435;   /* era #ff681c */
  --page:   #F4F6FC;   /* era #f2f6fc */
}

/* ---- 4 · VARIANTES CON OPACIDAD ------------------------------
   Tailwind inlinea el hex en cuanto hay opacidad, asi que estas no
   siguen al token y quedarian desfasadas respecto de su propia base.
   Solo las que existen en la pagina: medidas, son 27 en total y casi
   todas en rellenos o sombras. */
.bg-slate-200\/80    { background-color: #DCE4F5CC !important; }
.border-slate-200\/60{ border-color: #DCE4F599 !important; }
.bg-sky-500\/20      { background-color: #3B7DEC1F !important; }  /* 20%->12%, ver seccion 7c */
.border-sky-500\/20  { border-color: #3B7DEC33 !important; }
.border-sky-500\/25  { border-color: #3B7DEC40 !important; }
.border-sky-500\/30  { border-color: #3B7DEC4D !important; }
.border-sky-500\/40  { border-color: #3B7DEC66 !important; }
.from-sky-500\/10    { --tw-gradient-from: #3B7DEC1A !important; }
.border-sky-200\/80  { border-color: #BBD4FACC !important; }
.border-sky-200\/90  { border-color: #BBD4FAE6 !important; }
.shadow-sky-400\/50  { --tw-shadow-color: #58A9F480 !important; }
.shadow-sky-500\/20  { --tw-shadow-color: #3B7DEC33 !important; }
.shadow-amber-500\/50{ --tw-shadow-color: #F9743580 !important; }

/* ---- 5 · NARANJA COMO TEXTO · FALLO DE CONTRASTE -------------
   Medido en vivo contra el fondo efectivo compuesto:

     "OFF COURSE"  #F97435 sobre #F2F6FB  =  2.55:1
     "+4.1%"       #FF853F sobre #F2F5FB  =  2.22:1

   WCAG pide 4.5:1 para texto de ese tamanio. Los dos fallan, y son
   justamente el indicador de que un presupuesto se rompio: el estado
   mas importante de la pantalla era el menos legible.

   El naranja de marca #F97435 da 2.77:1 sobre blanco — no llega ni
   al 3:1 de texto grande. No es un problema de estos dos elementos:
   el naranja de marca NO PUEDE usarse como texto sobre claro, nunca.
   Rellena, subraya, marca un borde. Para leerse existe --h-accent-ink. */
.helm-status-title,
.helm-drift-value,
.helm-drift-label {
  color: var(--h-bad-ink) !important;   /* Danger ink · 5.96:1 */
}
/* Por que Danger y no Warning: el manual lista los estados como
   Optimized / Review / Over budget / Syncing. "OFF COURSE" con $146 POR
   ENCIMA del tope es una brecha consumada, no una tendencia — le
   corresponde Danger. Si la lectura correcta fuera "va a romperse pero
   todavia no", el token es --h-warn-ink y es cambiar una linea. */

/* ---- 6 · NOTA ABIERTA · no hay amarillo de advertencia --------
   La escala "amber" de este proyecto era naranja, con el mismo tono
   que el acento de marca (dE 11.4 entre si, misma familia). Es decir:
   un elemento naranja en el producto es ambiguo — no se distingue si
   destaca algo o si avisa de un problema.

   La marca si declara amarillo entre los estados (verde, rojo,
   amarillo), asi que --h-warn / --h-warn-ink de la seccion 1 quedan
   definidos y listos. Lo que NO hago es repintar solo: decidir cuales
   de los elementos naranjas actuales son "advertencia" y cuales son
   "acento" es una decision de producto, no una que deba adivinar yo
   desde el CSS. Queda para revisar juntos. */

/* ---- 7 · FALLOS DE CONTRASTE CON INTENCION CLARA -------------
   Auditados los 308 nodos de texto de la pagina contra su fondo
   efectivo compuesto. En claro quedaban 11 fallos; 3 eran falsos
   positivos (visibility:hidden). De los 8 reales, estos 3 tienen una
   intencion inequivoca y se arreglan aca. */

/* a · la insignia del bot: blanco sobre el naranja de marca da 2.77:1.
   Es el mismo limite de la seccion 5 — el naranja de marca no sostiene
   texto. Se rellena con el naranja profundo: blanco sobre #B8400A
   da 5.56:1 y el color sigue leyendose como naranja. */
/* Antes tenia blanco sobre el naranja de marca (2.77:1). Mi arreglo
   anterior lo relleno con el naranja profundo, que cumplia contraste
   pero seguia gastando el unico naranja que permite la regla 25/5/1 en
   un contador de notificaciones. Un contador no es un insight
   accionable: va en azul. */

/* b · el boton de periodo activo tenia texto blanco sobre un relleno
   que en claro no se pintaba: 1.14:1, practicamente invisible.
   Un toggle seleccionado se rellena — blanco sobre el azul de accion
   da 6.28:1. */
.finops-range-switch .is-active,
.utility-pill .period-button.is-active,
.finops-range-switch button.is-active {
  background-color: var(--h-action) !important;
  color: #FFFFFF !important;
  border-color: var(--h-action) !important;
}

/* c · los chips sobre bg-sky-500/20 quedaban en 4.40:1 — a 0.10 de
   cumplir, y este si lo introduje yo al mover el azul de las utilidades
   sky al azul de marca.

   Intente primero oscurecer el texto, pero estos chips no usan un solo
   token: unos son text-sky-300 y otros text-sky-600, asi que perseguir
   el token dejaba instancias fuera. Se aclara el RELLENO en la seccion 4
   (20% -> 12%): sube el contraste sin importar que token use el texto,
   y una sola linea cubre los cuatro chips. Verificado: los 2 fallos
   desaparecen. */
[class*="bg-sky-500/20"] { color: #1D40B8; }

/* ---- 8 · PENDIENTE DE DECISION · texto claro sobre fondo claro ---
   Los 4 fallos restantes comparten una sola causa estructural, y no
   los toco porque arreglarlos bien exige decidir el diseno, no el CSS:

     "Off course"           blanco       sobre #F1F5FB  =  1.09:1
     "Preview correction"   blanco       sobre #FFFFFF  =  1.00:1
     "$146 projected over"  #CBDCF1      sobre #F1F5FB  =  1.28:1
     "HORIZON"              #91B8EA      sobre #F1F5FB  =  1.87:1

   Todos estan en el panel del helm y en el lanzador del bot, y todos
   son texto pensado para una superficie OSCURA que en el tema claro no
   se pinta. Es el reflejo exacto del problema que ya tenemos en el
   tema oscuro con los bg-white horneados en el markup.

   Hay dos salidas y son excluyentes: o el panel recupera su fondo
   navy y el texto claro queda bien, o el panel se asume claro y hay
   que reescribir esos textos a ink. La primera conserva el diseno que
   alguien penso; la segunda es mas barata. Es tu decision, no mia. */

/* ---- 9 · LITERALES SUELTOS EN index.css ----------------------
   Dos reglas de index.css hardcodean un color en vez de usar token, y
   por eso no las alcanza nada de lo anterior. Son 178 usos entre las
   dos. Los valores estan cerca del token que les corresponde, asi que
   es snap, no decision. */
.budgets-table tbody td { border-color: var(--h-border) !important; }  /* era #e2eaf3 */
.chartplotter-latest p  { color: var(--hz-ink-3, #27447E) !important; } /* era #294361 */

/* ---- 10 · LA RAMPA DE TEXTO SECUNDARIO NO ES DERIVA ----------
   Conviene dejarlo escrito porque a simple vista parecen colores
   sueltos: --hz-ink-2 #1B3266, --hz-ink-3 #27447E y --hz-ink-4 #3A5A94
   son la rampa de texto secundario que declara horizon-skin.css, y su
   comentario dice "navy, no gris" — es decir, es deliberada y cumple
   el manual, que pide profundidad en navy y prohibe los grises
   lavados. Son ~334 usos y NO se tocan. */

/* ---- 11 · LOS PUNTOS PULSANTES -------------------------------
   Venian en #FF853F, el amber-400 original, que no es un valor del
   manual. Al ser un literal hardcodeado no lo alcanzaba la
   redefinicion de tokens.

   Mi primer arreglo los puso los dos en el acento naranja, razonando
   que un beacon es una alerta accionable. Estaba mal: al mirar QUE
   anota cada uno, ninguno de los dos es el acento.

   - El del helm dice "OFF COURSE · $146 projected over". Eso es el
     estado Over budget, y el mismo estado ya se pinta #E5484D en los
     puntos de la tabla de budgets. Dos colores para un estado es
     justo lo que veniamos arreglando.
   - El de systems load dice "LIVE TRACKING". Es liveness, no alerta, y
     el manual lo tiene resuelto: "Syncing = blue".

   Van por la clase de estado del contenedor, no fijos, para que sigan
   al dato si cambia. */
.navigation-helm-bar.is-off-course .hz-beacon,
.navigation-helm-bar.is-off-course .hz-beacon + span,
.navigation-helm-bar.is-off-course .hz-beacon ~ span {
  background-color: var(--h-bad) !important;      /* Over budget */
}
/* CORRECCION. Aqui puse azul razonando "Syncing = blue" del manual,
   pero ese pill dice LIVE TRACKING, no syncing — y son estados
   distintos: syncing es una accion en curso, live es una condicion
   estable y sana.

   Lo delata el propio contenedor: el pill es VERDE y el punto quedaba
   azul. Y la pagina ya tiene su convencion en otros dos sitios —
   "Financial telemetry live" y el "Live" del hero — los dos con punto
   verde. Live = Success, en los tres.

   De paso: esos dos usaban #18A970 y #23BF76, y ninguno era el token.
   Dos verdes sueltos mas, la misma deriva que tenia la familia roja. */
.systems-load-panel .hz-beacon,
.systems-load-panel .hz-beacon + span,
.systems-load-panel .hz-beacon ~ span,
.live-state > span,
.finops-feedback-strip.is-healthy i,
.finops-feedback-strip.is-healthy > span > i {
  background-color: var(--h-ok) !important;   /* live = Success */
}
/* cualquier otro beacon que aparezca: azul, no acento. El naranja se
   gana por ser EL insight de la pantalla, no por pulsar. */
.hz-beacon,
.hz-beacon + span,
span.hz-beacon ~ span { background-color: var(--h-action) !important; }

/* TERCER CONTEXTO que el fallback de arriba no conocia: el badge "LIVE"
   de las tarjetas .finops-kpi. Viene marcado bg-emerald-500 -- el badge
   entero ya es verde (fondo emerald-50, borde emerald-200, texto
   emerald-700) -- pero el fallback de azul le ganaba al verde de
   Tailwind porque ninguno de los dos define el contenedor de estado que
   los dos casos de arriba si tienen. Mismo criterio que el resto de
   este bloque: liveness = Success, no accion. Por especificidad
   (dos clases) gana sobre el fallback de una. */
.hz-beacon.bg-emerald-500,
.hz-beacon.bg-emerald-500 + span,
span.hz-beacon.bg-emerald-500 ~ span { background-color: var(--h-ok) !important; }

/* ---- 11b · LA UNICA REGLA NARANJA ---------------------------
   El manual: "Insight card = SOLO regla naranja a la izquierda (sin
   texto/boton naranja)". La tarjeta del radar es exactamente eso — el
   insight accionable de la pantalla, con su link "Inspect Google Cloud
   spend" — y su regla estaba en #F59E0B, el ambar de Warning.

   Con esto el acento queda gastado UNA vez y en el lugar que el manual
   define, en vez de repartido en puntos que pulsan. */
.radar-active-signal { border-left-color: var(--h-accent) !important; }

/* ---- 12 · REGLA 25/5/1 · RESUELTA ---------------------------
   El manual pide EXACTAMENTE 1 naranja por pantalla: "si todo es
   naranja, nada lo es". Se llego a 5 elementos naranjas.

   Quedo 1: la regla izquierda de la tarjeta de insight del radar.
   Los otros cuatro no se repintaron por gusto — cada uno tenia un
   destino que el manual ya definia:
     iconos de categoria  -> azul institucional (decision de Dario)
     beacon del helm      -> Danger, es Over budget
     beacon live tracking -> azul, "Syncing = blue"
   El naranja dejo de ser decoracion y volvio a significar algo. */

/* ---- 13 · TARJETAS DE CATEGORIA · identidad vs estado --------
   Esto lo rompi yo en la seccion 2 y hay que dejarlo escrito.

   Los tres iconos de categoria venian con clases DISTINTAS en el
   markup — bg-violet-600, bg-sky-600, bg-amber-500 — porque eran tres
   colores de categoria. Al colapsar violet-600 y sky-600 los dos a
   #2450E4 quedaron dos iconos azules identicos y uno ambar. Resultado:
   se perdio la distincion de categoria y el tercero se leia como
   alerta sin serlo, que es precisamente lo que el manual prohibe
   ("naranja en chart = categoria, no alerta").

   DECISION (Dario, 14-08): los tres iconos van en el azul institucional
   de Cloudbeach, no en el orden de series. Probe primero el orden fijo
   del manual (blue -> teal -> orange) y quedaba correcto por norma pero
   metia tres marcas de color distintas en una fila que ya lleva estado
   en la barra y en el pill: demasiados idiomas a la vez.

   Con un solo azul, el color deja de competir: la categoria la dicen el
   nombre y la lista de proveedores, y el unico color con significado en
   la fila es el estado. Ademas libera el naranja, que es lo que la
   regla 25/5/1 venia pidiendo — el acento vuelve a estar disponible
   para el insight accionable en vez de gastarse en un icono.

   Nota: cloudbeach.com pinta #1A4FD6, a dE 7.5 del token. Eso es deriva
   del sitio, no el valor de marca; aqui va el del manual, #2450E4. */
.systems-load-card .rounded-xl.bg-violet-600,
.systems-load-card .rounded-xl.bg-sky-600,
.systems-load-card .rounded-xl.bg-amber-500 {
  background-color: var(--h-action) !important;   /* Cloudbeach Blue · glifo blanco 6.28:1 */
}

/* el pill dice "% OF CAP" — es estado, asi que sigue a la clase de
   estado de la tarjeta, no a un umbral propio. Antes dos tarjetas
   is-warn mostraban pill azul y una ambar: mismo estado, tres lecturas. */
.systems-load-card.is-warn .rounded-full.border {
  color: var(--h-warn-ink) !important;
  background-color: rgba(245,158,11,.12) !important;
  border-color: rgba(245,158,11,.38) !important;
}
.systems-load-card.is-bad .rounded-full.border {
  color: var(--h-bad-ink) !important;
  background-color: rgba(238,0,51,.12) !important;
  border-color: rgba(238,0,51,.38) !important;
}
/* Y el caso sano, que hasta ahora no existia: las tres tarjetas
   estaban en la banda de atencion, asi que el hueco no se veia. Al
   poner los tres estados salio a la vista -- barra verde con pastilla
   azul, el mismo estado dicho de dos maneras. Contraste medido del
   ink verde sobre su propio tinte: 4.79:1. */
.systems-load-card:not(.is-warn):not(.is-bad) .rounded-full.border {
  color: var(--h-ok-ink) !important;
  background-color: rgba(31,169,92,.12) !important;
  border-color: rgba(31,169,92,.38) !important;
}

/* ---- 14 · EL CONTADOR "OVER OR AT CAP" -----------------------
   Estaba en #A05F02 (--hz-warn-ink). Es un valor de marca, pero a 28px
   un ambar oscurecido lee como mostaza sucia, y encima competia con el
   rojo de PROJECTED MONTH-END por ser el foco.

   El manual pide "1 focal point por vista" y "dot+label+color, NUNCA
   color solo". El foco de esta fila es la proyeccion en rojo; este es
   un recuento y su significado ya lo llevan el titulo de la tarjeta y
   la bajada "4 sources · 1 person". Va en navy como Spend y Budget. */
.finops-kpi--watch .text-3xl,
.finops-kpi--watch .text-2xl { color: var(--h-ink) !important; }

/* ---- 15 · RITMO INTERNO DE LAS TARJETAS KPI ------------------
   Se mantiene la base que ya tenian — fondo blanco, borde, radio,
   sombra hairline — y se unifica lo que estaba desparejo entre las
   cuatro. Todas las medidas caen en la escala de 4px del manual, y el
   radio y el padding son los que el manual fija para card (16 / 20-24).

   El pie va en --hz-ink-3, un paso por debajo del cuerpo: es contexto
   de alcance, no dato. Asi la cifra sigue siendo el unico foco. */
.finops-kpi {
  border-radius: 16px !important;
  padding: 20px !important;
}
.finops-kpi > div:first-of-type { margin-bottom: 12px !important; }
.finops-kpi .text-3xl,
.finops-kpi .text-2xl { line-height: 1 !important; }
.finops-kpi .mt-4.pt-3 {
  margin-top: 16px !important;
  padding-top: 12px !important;
  border-top-color: var(--h-border) !important;
}
.finops-kpi .mt-4.pt-3 span { color: var(--hz-ink-3, #27447E) !important; }

/* el pie de proveedores quedo vacio al quitar la lista: si no tiene
   contenido no debe dejar el filete del border-top colgando */
.systems-load-card > div:empty { display: none !important; }

/* ---- 16 · RADAR · solo los tres colores de estado ------------
   De las seis bolitas, cinco ya eran rose / amber / emerald y una era
   bg-sky-400. El sky no es un estado: es el color de las anillas y del
   barrido del propio radar, asi que una bolita sky se confundia con la
   escenografia en vez de leerse como salud.

   Se corrigio en el markup (bg-emerald-500) y no por override, para que
   la bolita lleve una clase de estado de verdad. Este bloque solo cierra
   la puerta a que vuelva a colarse otro color. */
.radar-blip-core { box-shadow: none !important; }
.radar-blip-core.bg-sky-400,
.radar-blip-core.bg-sky-500,
.radar-blip-core.bg-blue-600,
.radar-blip-core.bg-violet-600 {
  background-color: var(--h-ok) !important;
  border-color: #99DEBC !important;
}

/* ---- 17 · LAS BAJADAS COMPARTEN LINEA DE BASE ----------------
   NOTA: esto es layout, no color. Va aqui para no sumar una cuarta
   hoja y un cuarto enlace por tres reglas; si el archivo sigue
   creciendo por este lado, conviene separarlo.

   Medido a 4 columnas: las tarjetas ya median lo mismo (el grid las
   estira, 271px las cuatro), pero los pies caian a 135, 171, 126 y
   147px. Cuatro descripciones a cuatro alturas distintas leen como
   cuatro tarjetas sin relacion.

   Con la tarjeta en columna flex y el pie en margin-top:auto, el pie
   se ancla abajo y los cuatro comparten linea de base (155px). El
   `:not(.absolute)` deja fuera la decoracion posicionada de la
   primera tarjeta, que no debe entrar en el flujo. */
.finops-kpi { display: flex !important; flex-direction: column !important; }
.finops-kpi > div:not(.absolute) { flex: 0 0 auto; }
.finops-kpi .mt-4.pt-3 { margin-top: auto !important; }

/* ---- 18 · BARRA DE POSICION CONTRA EL TOPE -------------------
   Reemplaza los cuatro "sparklines" de las tarjetas KPI.

   POR QUE se cambiaron: no eran datos. Eran curvas Bezier escritas a
   mano — `M 0 32 Q 25 28, 40 18 T 70 14 T 100 8` — sin un solo punto
   de dato detras. Un garabato suave que parece una tendencia. En un
   panel financiero eso no es decoracion, es una tendencia que nadie
   midio, y el manual lo prohibe de dos maneras: "los numeros NO
   cuentan hacia arriba (theatre en pantalla financiera)" y "el numero
   es defendible antes que impresionante (scope+period+basis)".
   Encima venian con #d92a20, #0864ee y #e35310 hardcodeados, tres
   colores que ya habiamos retirado.

   QUE muestran ahora: la posicion real del valor contra el tope, que
   es el unico dato que cada tarjeta ya declara por escrito.

   El riel va de 0 a 110% del tope, no a 100%. Asi la marca del tope cae
   al 90.909% del ancho y queda sitio para VER el rebase pasar la linea
   en vez de que la barra se quede clavada al final. Relleno plano y
   arranque en 0, como pide el manual para datos.

     projected  104.06% del tope -> cruza la marca, en Danger
     spend       98.46% del tope -> justo por debajo, en Warning
     budget        el tope mismo -> en la marca, en navy (referencia)
     over/at cap   es un RECUENTO, no un ratio: no lleva grafico, porque
                   la tarjeta no declara denominador y no voy a inferirlo
                   de otra tarjeta. */
.hz-cap {
  position: relative;
  display: block;
  width: 100%;
  height: 6px;
  border-radius: 999px;
  background: var(--h-sunken);
}
.hz-cap > i {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: calc(var(--v) * 1%);
  border-radius: 999px;
  background: var(--h-warn);
}
.hz-cap--bad > i { background: var(--h-bad); }
.hz-cap--ref > i { background: var(--hz-ink-4, #3A5A94); }
/* la marca del 100%: el umbral tiene que ser legible sin leyenda */
.hz-cap::after {
  content: "";
  position: absolute;
  left: 90.909%;
  top: -4px; bottom: -4px;
  width: 2px;
  border-radius: 1px;
  background: var(--h-ink);
  opacity: .5;
}

/* ---- 19 · RETICULA COMPARTIDA DE LA FILA DE KPI --------------
   Medido a 1680px, ANTES: las cuatro tarjetas median lo mismo pero
   nada dentro de ellas se alineaba.

     base de las cifras   -222 / -227 / -227 / -227   (5px de desvio)
     filete del pie       -115 / -136 / -115 / -136   (21px de escalon)

   Un escalon de 21px en los filetes es lo que hacia que la fila
   pareciera cuatro tarjetas sueltas en vez de una fila. Y ningun
   grafico iba a arreglar eso — de hecho los graficos lo tapaban.

   La causa de los 5px: la primera tarjeta llevaba un pill "+$146 OVER"
   en la fila de la etiqueta, que la hacia mas alta (24px contra 16px) y
   empujaba su cifra fuera de la base comun. Ese pill decia exactamente
   lo mismo que la linea "+$146 over budget" de abajo, asi que se quito:
   se gana la alineacion y se pierde una repeticion.

   La causa de los 21px: dos de los cuatro pies envuelven a 3 lineas y
   dos a 2. Se fija la altura del bloque del pie en 2 lineas para que el
   filete caiga siempre en el mismo sitio, sin recortar el texto. */
/* OJO con el selector: la primera tarjeta tiene como primer hijo un div
   decorativo con position:absolute, asi que `:first-of-type` apuntaba a
   ese y no a la fila de la etiqueta — la alineacion no se movia. La fila
   de la etiqueta se identifica por su `mb-2`. */
.finops-kpi > div.mb-2 { min-height: 20px !important; align-items: center !important; }
/* 12px de padding-top + 2 lineas de 14px a 1.35 = 49.8px. Con 46 el pie
   de una sola linea quedaba 5px mas abajo que los de dos. 52 cubre las
   dos lineas y alinea los cuatro filetes. */
.finops-kpi .mt-4.pt-3 { min-height: 52px; align-items: flex-start; }
.finops-kpi .mt-4.pt-3 > span { line-height: 1.35 !important; }

/* ---- 20 · EL COCKPIT ES REACT: EL HTML NO ES LA CAPA FIABLE ---
   Descubierto al intentar quitar el segundo timestamp de la primera
   tarjeta. app.html es solo el snapshot pre-renderizado; el que manda
   es app.js.

   El pie de esa tarjeta tiene DOS spans en el JSX: la descripcion y el
   contador. Borre el segundo del HTML, y al hidratar React reconcilio
   POR POSICION: escribio el texto del contador dentro de mi primer
   span. Resultado, "5 budgets at or over cap" desaparecio y quedo
   "Forecast recalculated 7s ago" con las clases del primero.

   O sea: quitar del DOM un nodo que React espera no lo elimina, hace
   que React parchee el elemento equivocado. El span esta restaurado y
   lo que sobra se oculta desde aqui, que es la capa que React no pisa.

   Este segundo timestamp era redundante: el hero ya lleva el last-sync
   de la vista, y el manual pide uno por vista, no uno por tarjeta. */
.finops-kpi--projected .mt-4.pt-3 > span:last-child { display: none !important; }

/* el pill "+$146 OVER" repetia literalmente la linea "+$146 over
   budget" de la propia tarjeta. Se quito del HTML, pero si React
   vuelve a montarlo esta regla lo mantiene fuera. */
.finops-kpi--projected div.mb-2 > span[class*="rounded-full"] { display: none !important; }

/* ---- 21 · DOS BARRAS DE SCROLL ------------------------------
   Medido: scrolleaban dos elementos a la vez.
     shell   .bridge-page          4874 de contenido en 4814 -> 288px
     cockpit .finops-dashboard     4874 de contenido en 4814 ->  60px
   El cockpit se lleva su propia barra por 60px de exceso mientras el
   shell ya scrollea el iframe entero. Dos barras para un solo eje.

   El scroll lo hace el shell, que es el que tiene el alto real. El
   contenedor de dentro deja de scrollear y su exceso pasa al padre. */
.finops-dashboard { overflow-y: visible !important; }

/* ---- 22 · REGLA DE COLOR DE LA FILA DE KPI -------------------
   Auditada la fila entera, el desajuste era UNO y estaba en la misma
   ranura de dos tarjetas distintas:

     tarjeta 1   "+$146 over budget"    -> bad-ink   (estado)
     tarjeta 2   "▲ 6% vs last month"   -> ACTION    (azul de accion)

   Dos idiomas para la misma cosa. Y el azul ahi es del todo incorrecto,
   no solo incoherente: el manual define --h-action como "CTAs, links,
   interactivo". Un delta no se puede clicar.

   La prueba de que el azul si se usa bien en el resto de la pagina son
   los "Edit · Details" de la tabla de budgets: son azules porque son
   enlaces. El delta del KPI era el unico DATO pintado con el color de
   lo interactivo.

   LA REGLA, derivada del documento y no inventada:

     1. navy por defecto — la cifra y su contexto viven en la rampa ink
     2. color de estado SOLO si hay un estado, y SIEMPRE con su etiqueta
        ("NUNCA color solo", por eso "$3,746" rojo es valido: lo
        acompania "+$146 over budget")
     3. el azul de accion NUNCA en un dato — es para lo que se clica
     4. el naranja no entra aca (ver nota abajo)

   Por eso el delta pasa a la rampa navy: un +6% mensual no es ninguno
   de los estados que el manual define (Optimized / Review / Over budget
   / Syncing). Es informacion neutra — gastar 6% mas no es de por si
   bueno ni malo. Y la tarjeta 1 conserva el rojo porque "over budget"
   SI es un estado consumado y trae su etiqueta al lado.

   POR QUE NO EL NARANJA DE cloudbeach.com, medido:
     - el naranja del sitio es #F05A28, a dE 10.2 del #F97435 del
       manual. Es deriva del propio sitio; adoptarlo la importaria.
     - "$146 over budget" es una brecha consumada. El manual manda eso
       a Danger y reserva el acento para "insight que amerita accion",
       exactamente 1 por pantalla — y ese unico cupo ya lo gasta la
       regla naranja de la tarjeta de insight del radar.
     - de contraste no da: el naranja de marca como texto es 2.77:1.
       Habria que usar #B8400A, que a cuerpo grande lee marron. Ya lo
       vimos con el "5" mostaza de la cuarta tarjeta. */
.finops-kpi [class*="text-sky-"],
.finops-kpi [class*="text-blue-"],
.finops-kpi [class*="text-indigo-"],
.finops-kpi [class*="text-sky-"] * {
  color: var(--hz-ink-2, #1B3266) !important;
}

/* ---- 23 · LA MISMA REGLA, FUERA DE LA FILA DE KPI ------------
   Con la regla escrita, el barrido encontro 5 elementos mas pintados
   con el azul de accion sin ser clicables:

     "6 ACTIVE"          cuenta de senales del radar
     "98.5% UTILIZED"    chip de porcentaje
     "$3,600.00"         la cifra del tope dentro de la prosa
     "GC"                iniciales del avatar  <- este NO se toca
     (+ el delta del KPI, ya corregido en la seccion 22)

   Los tres primeros son datos: pasan a la rampa navy. Siguen
   destacando por el peso, que es como se enfatiza un numero dentro de
   una frase sin robarle el color a los enlaces.

   El "GC" era la cuarta y quedaba fuera por ser insignia y no dato,
   pero se elimino del markup por pedido: la frase de al lado ya dice
   "global cap" y el avatar no aportaba nada que el texto no diga. Al
   irse, esa excepcion sobra. */
.spend-radar-card [class*="text-sky-"]:not(a):not(button),
.systems-load-footer [class*="text-sky-"]:not(a):not(button):not(.rounded-lg) {
  color: var(--hz-ink-2, #1B3266) !important;
}
/* el chip de porcentaje mantiene su relleno teñido y solo cambia el
   texto: el relleno comunica "referencia", el texto es el dato */
.systems-load-footer [class*="bg-sky-500/20"] {
  color: var(--hz-ink-2, #1B3266) !important;
}

/* el ultimo: "96.9% used" en el resumen de budgets. Se acota al
   resumen y no al panel entero, porque el panel contiene los enlaces
   Edit/Details, que en azul estan correctos. */
.budgets-panel .budgets-summary [class*="text-sky-"],
.budgets-panel > :last-child [class*="text-sky-"]:not(a):not(button):not(.budget-row-actions *) {
  color: var(--hz-ink-2, #1B3266) !important;
}

/* ---- 24 · BOT CLAUDIO · avatar circular ----------------------
   El launcher del copilot lo crea app.js y su icono era un SVG dentro
   de un cuadrado de 42px con degradado azul. Ahora lleva la foto de la
   mascota, en circulo.

   El degradado de fondo se quita: con la foto encima no se ve, y
   dejarlo solo pinta un borde de color en el antialias del circulo.
   Queda un aro claro que separa la foto del navy del panel.

   La foto va a 192px para un slot de 42, o sea ~4.5x: nitida en
   pantallas retina sin pesar (52KB). */
.horizon-bot-launcher-icon,
.horizon-bot-avatar {
  border-radius: 50% !important;
  background: rgba(255,255,255,.10) !important;
  overflow: hidden;
  padding: 0 !important;
}
.horizon-bot-face {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}
/* el punto de estado se dibuja sobre el borde del circulo, no dentro */
.horizon-bot-launcher-icon > i {
  z-index: 2;
}

/* ---- 25 · BOT CLAUDIO · circulo + globo "Need a hand?" -------
   El launcher cerrado era una pastilla de 232px con el estado y el
   importe escritos. Pasa a ser SOLO un circulo de 60px con la cara, y
   el saludo sale en un globo animado.

   TRES COSAS QUE CONDICIONAN EL MONTAJE:

   1. El texto NO se borra del DOM, se oculta con display:none. app.js
      guarda referencias vivas al <strong> y al <em> de ese bloque
      (horizonBotState / horizonBotMeta) y les escribe el estado en cada
      tick. Quitarlos del HTML dejaria esas referencias en null —
      estan guardadas con `if`, asi que no romperia, pero el bot
      perderia su estado. Ocultos siguen actualizandose y el aria-label,
      que se construye leyendo horizonBotState.textContent, sigue
      diciendo la verdad.

   2. El globo va en .horizon-bot-shell::after, NO en el launcher: el
      launcher tiene overflow:hidden para el barrido de brillo de su
      propio ::before, y ahi dentro el globo quedaria recortado.

   3. El disparo por hover usa :has() ademas de :hover, porque el shell
      tiene pointer-events:none y no conviene depender de que el hover
      suba por la cadena desde el hijo.

   VOZ: "Need a hand?" — en ingles, corto y sin signos de exclamacion,
   que el manual prohibe expresamente. */

/* el launcher deja de ser pastilla y pasa a circulo */
.horizon-bot-launcher {
  grid-template-columns: 1fr !important;
  gap: 0 !important;
  min-width: 0 !important;
  width: 60px !important;
  min-height: 60px !important;
  height: 60px !important;
  padding: 0 !important;
  border-radius: 50% !important;
}
.horizon-bot-launcher-copy { display: none !important; }
.horizon-bot-launcher .horizon-bot-launcher-icon {
  width: 100% !important;
  height: 100% !important;
  border: 0 !important;
}
/* el contador se mete DENTRO del circulo: a 8px del borde entra
   completo sin que el recorte del radio le coma la esquina */

/* ---- el globo ---- */
.horizon-bot-shell::after {
  content: "Need a hand?";
  position: absolute;
  right: 72px;
  bottom: 18px;
  white-space: nowrap;
  padding: 9px 15px;
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--h-ink);
  font-family: var(--font-sans, "Poppins", sans-serif);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -.005em;
  box-shadow: 0 10px 26px -8px rgba(10,30,70,.34), 0 0 0 1px var(--h-border);
  pointer-events: none;
  opacity: 0;
  transform: translateX(10px) scale(.94);
  transform-origin: right center;
  transition: opacity .2s ease-out, transform .2s cubic-bezier(.2,.7,.3,1);
  /* saludo de cortesia: asoma una vez al entrar y se retira solo */
  animation: hzHail 5.4s 1.4s cubic-bezier(.2,.7,.3,1) 1 forwards;
}
@keyframes hzHail {
  0%   { opacity: 0; transform: translateX(10px) scale(.94); }
  10%  { opacity: 1; transform: translateX(0) scale(1); }
  74%  { opacity: 1; transform: translateX(0) scale(1); }
  100% { opacity: 0; transform: translateX(10px) scale(.94); }
}
/* al pasar el raton o al enfocar, la animacion se retira y manda la
   transicion — si no, el fill:forwards del saludo dejaria el globo
   clavado en su fotograma final y el hover no haria nada */
.horizon-bot-shell:hover::after,
.horizon-bot-shell:has(.horizon-bot-launcher:hover)::after,
.horizon-bot-shell:has(.horizon-bot-launcher:focus-visible)::after {
  animation: none;
  opacity: 1;
  transform: translateX(0) scale(1);
}
/* con el panel abierto el globo no tiene nada que hacer */
.horizon-bot-shell.is-open::after { content: none; }

@media (prefers-reduced-motion: reduce) {
  .horizon-bot-shell::after { animation: none; transition: none; }
}

/* ---- 26 · EL CONTADOR Y EL BORDE DEL CIRCULO -----------------
   El "1" se veia mal por dos cosas sumadas, no una:

     a) un aro de 1.8px en rgba(3,26,59,.9) — un cerco oscuro y grueso
        sobre la foto
     b) un digito de 14px dentro de un circulo de 21px, o sea sin aire

   El (b) lo cause yo: la seccion 4 de hrzn-type.css metio
/* Con un solo `.horizon-bot-launcher` (0,1,0) la sombra perdia: hay otro
   !important de igual especificidad mas abajo en la cascada, y a igual
   peso gana el ultimo. Con el shell delante son (0,2,0) y no hay empate.
   Medido: en reposo computaba `none` incluso poniendo la sombra inline. */
/* ---- 27 · EL CIRCULO SE PERDIA CONTRA LA PAGINA --------------
   Medido: el borde exterior de la foto promedia #A8A5A4 y da 2.24:1
   contra el canvas #F1F5FB. Sin arista de contraste, el circulo lee
   como una manchita gris y no como un boton.

   Se resuelve con un anillo en el azul de marca, que da 5.74:1 contra
   la pagina. Y es el color correcto por sistema, no solo por contraste:
   el azul de accion significa "esto se clica", y esto se clica.

   Tres capas, todas con box-shadow y NINGUNA con border, que es lo que
   pediste:
     2px blancos   separan la foto gris del anillo
     3px azules    la arista que lo hace visible
     halo al 16%   lo despega del fondo sin engordar la sombra
   + la sombra de caida suave que ya tenia.

   El circulo pasa de 60 a 64px: con 5px de anillo alrededor, mantener
   60 le comeria presencia a la cara. */
.horizon-bot-shell .horizon-bot-launcher,
.horizon-bot-shell .horizon-bot-launcher:hover {
  border: 0 !important;
  width: 64px !important;
  height: 64px !important;
  min-height: 64px !important;
  box-shadow: 0 0 0 2px #FFFFFF,
              0 0 0 5px var(--h-action),
              0 0 0 9px rgba(36, 80, 228, .16),
              0 10px 24px -8px rgba(10, 30, 70, .32),
              0 2px 6px rgba(10, 30, 70, .14) !important;
}


/* ---- 28 · ESTADO vs NO-ESTADO · la frontera del naranja ------
   Auditada la pagina, habia CINCO valores en la familia naranja/rojo y
   solo dos eran estado:

     #F59E0B  26 usos  ESTADO Warning
     #E5484D  15 usos  ESTADO Danger
     #D5372D   9 usos  no — texto de deriva del chartplotter
     #F97435   2 usos  no — degradado del helm y del bot
     #FF853F   1 uso   no — literal viejo en el degradado del helm

   Los tres ultimos eran el problema: casi-rojos y naranjas sueltos que
   parecen estado sin serlo. Van todos al naranja de no-estado.

   Y no es una lectura mia: horizon-skin.css ya lo tenia escrito —
   "gradiente azul->naranja = trayectoria en el tiempo. Verde/amarillo/
   rojo = salud. Mezclar los dos lenguajes es lo que hace ilegible un
   tablero". El naranja del final de ese degradado nunca fue salud.

   LA FRONTERA, de una vez:
     salud          -> verde #1FA95C / ambar #F59E0B / rojo #EE0033
     trayectoria    -> azul -> #F05A28
     accion posible -> #F05A28 (la regla del insight, 1 por pantalla)
     interactivo    -> azul #2450E4
   Ningun otro naranja ni rojo. */

/* el texto de deriva del chartplotter: era #D5372D, un cuarto rojo
   suelto. Va al naranja legible, que cumple 4.65:1 — el vivo no
   serviria aqui porque es texto. */
.chartplotter-overview strong.is-drifting,
.chartplotter-course.is-drifting,
.chartplotter-overview .is-drifting,
.chartplotter-card .is-drifting {
  color: var(--h-accent-ink) !important;
}

/* el extremo calido del degradado de trayectoria */
.helm-track > div {
  background: linear-gradient(90deg, var(--h-action) 0%, var(--h-accent) 100%) !important;
  box-shadow: none !important;
}

/* el punto de hoy en el grafico es trayectoria, no alerta */
.chartplotter-svg path[stroke-dasharray="6 6"] { stroke: var(--h-accent) !important; }

/* ---- 29 · LA FAMILIA DE ROJOS SUELTOS DEL CHARTPLOTTER -------
   El primer barrido solo vio los visibles. Grepeando index.css aparece
   que el chartplotter tiene SEIS rojos propios, ninguno del sistema:

     #d5372d   texto de deriva del overview y del course
     #b82c23   .chartplotter-latest strong
     #ce3027   .chartplotter-summary .is-drifting strong
     #ffaca4   texto del chip .chartplotter-status.is-drifting
     #d92a20   su relleno, al 16%
     #f3564b   su borde, al 35%

   Seis valores para una sola idea. Y ninguno es salud: en el
   chartplotter la deriva es TRAYECTORIA — el mismo lenguaje del
   degradado azul->naranja. Van todos al naranja de no-estado, con el
   -ink donde son texto porque el vivo da 3.39:1 y no se puede leer. */
.chartplotter-latest strong,
.chartplotter-summary .is-drifting strong,
.chartplotter-overview strong.is-drifting,
.chartplotter-course.is-drifting,
.chartplotter-card .is-drifting strong {
  color: var(--h-accent-ink) !important;
}
.chartplotter-status.is-drifting {
  color: var(--h-accent-ink) !important;
  background: rgba(240, 90, 40, .12) !important;
  border-color: rgba(240, 90, 40, .38) !important;
}
.chartplotter-summary .is-drifting,
.chartplotter-course.is-drifting {
  background: linear-gradient(135deg, rgba(240, 90, 40, .07), #FFFFFF) !important;
}

/* ---- 30 · EL TOKEN HEREDADO DEL NARANJA ----------------------
   --hz-orange seguia en #F97435 y horizon-skin lo usa 8 veces, asi que
   el naranja viejo reaparecia por ahi. Se alinea con la decision. */
:root:not([data-theme="dark"]) { --hz-orange: #F05A28; }


/* ---- 31 · EL CIRCULO GIGANTE DEL GRAFICO · regresion mia -----
   La seccion 28 puso `fill` en TODOS los circle del punto de hoy. Uno
   de ellos es .chartplotter-point-hit con r=19: un circulo invisible
   que solo existe para agrandar el area de clic. Al rellenarlo opaco
   aparecio un disco enorme sobre el grafico.

   Los circulos de ese punto son tres y cada uno tiene su trabajo:
     r=12  halo animado, opacidad ~0.22
     r=6   el marcador visible
     r=19  el area de clic, SIEMPRE transparente
   Asi que la regla se acota al marcador y al halo, y el hit vuelve a
   ser invisible.

   El marcador del pronostico vuelve a Danger: la linea punteada es
   trayectoria (naranja), pero el punto donde aterriza es la brecha, y
   una brecha es estado. Naranja que termina en rojo cuenta la historia
   completa. */
.chartplotter-point-hit,
.chartplotter-point--today .chartplotter-point-hit,
.chartplotter-point--forecast .chartplotter-point-hit {
  fill: transparent !important;
}
/* EN EL GRAFICO NO ENTRA EL ROJO (decision de Dario): solo el naranja
   de Cloudbeach y el azul con su degradado. Yo habia dejado el punto del
   pronostico en rojo de estado razonando que una brecha es un estado —
   pero si el grafico habla de trayectoria, el rojo de salud no tiene
   nada que hacer ahi. Corregido.

   Al quitarlo se abria un problema: con los dos puntos en naranja se
   pierde la diferencia entre AHORA y PROYECTADO. Se resuelve con los
   dos unicos colores permitidos — cada punto toma el color del tramo
   que cierra:
     punto de hoy        cierra la linea solida    -> azul
     punto de pronostico cierra la punteada        -> naranja
   Asi el degradado azul->naranja se lee tambien en los extremos. */
.chartplotter-point--today .chartplotter-point-marker,
.chartplotter-point--today circle[fill="#ff7a2c"] {
  fill: var(--h-action) !important;
}
.chartplotter-point--forecast .chartplotter-point-marker,
.chartplotter-point--forecast circle[fill="#ef473a"] {
  fill: var(--h-accent) !important;
}
/* la etiqueta FORECAST del eje: el naranja vivo da 3.39:1 y es texto,
   asi que va el -ink, que es el mismo tono a 4.65:1 */
.chartplotter-svg text[fill="#ef473a"] { fill: var(--h-accent-ink) !important; }
:root:not([data-theme="dark"]) { --hz-bad: #EE0033; --hz-bad-ink: #CC002B; }

/* ---- 32 · LOS OUTLINES DE SEVERIDAD DEL RADAR ----------------
   Ultimo resto del rojo viejo: horizon-skin.css pinta el halo de las
   bolitas con literales, no con tokens —
   `.radar-blip[data-severity="critical"] .radar-blip-core
     { outline: 2px solid rgba(229,72,77,.2) }`
   y sus equivalentes de warning y healthy. Son 2px al 20% sobre puntos
   de 3px, casi invisibles, pero son el rojo anterior y por eso el
   inventario seguia marcando un suelto.

   Se alinean con los tres tokens en vez de editar esa hoja, que se
   regenera. */
.radar-blip[data-severity="critical"] .radar-blip-core { outline-color: rgba(238, 0, 51, .22) !important; }
.radar-blip[data-severity="warning"]  .radar-blip-core { outline-color: rgba(245, 158, 11, .20) !important; }
.radar-blip[data-severity="healthy"]  .radar-blip-core { outline-color: rgba(31, 169, 92, .20) !important; }
/* y sus bordes, que vienen de la escala rose/amber/emerald ya re-anclada */
.radar-blip-core.bg-rose-500    { border-color: var(--color-rose-300) !important; }
.radar-blip-core.bg-amber-500   { border-color: var(--color-amber-300) !important; }
.radar-blip-core.bg-emerald-500 { border-color: var(--color-emerald-300) !important; }

/* ---- 33 · LOS DEGRADADOS DEL SVG DEL CHARTPLOTTER ------------
   La barra de capacidad no era un div: es un <rect> pintado con
   url(#budgetCapacityBar), y el trazo de la linea usa otro,
   #minimalActualStroke. Los valores del markup no eran de la paleta —
   venian del diseno original:

     #011A3B -> #1450C4 -> #4FC3E8 -> #FFE066 -> #E8630D

   Se corrigen desde aqui y no en el markup porque `stop-color` es una
   propiedad estilizable por CSS: no hay que tocar el SVG.

   OJO CON EL CONTEO: la primera version de este bloque pisaba CUATRO
   paradas (y tres en el trazo) porque asi era el degradado cuando se
   escribio. Hoy los dos tienen CINCO, asi que las ultimas quedaban sin
   pisar y seguian pintando el amarillo #FFE066 al 62% y un naranja
   #E8630D fuera de paleta al 100% — el amarillo suelto que se veia en
   la mitad derecha de la linea. Ademas, con solo tres anclas el trazo
   remataba en el naranja ya al 48%: el cruce azul->naranja se estiraba
   sobre 23 puntos y en el medio daba un violeta que no es de nadie.
   Para que no vuelva a pasar, los hex del markup se actualizaron a
   estos mismos valores: si un dia esta hoja no carga, el SVG ya pinta
   los colores correctos por su cuenta.

   Los dos degradados cuentan lo mismo, asi que comparten las cinco
   anclas, todas institucionales:

     0%   --h-ink     #0A1E46   azul oscuro
     25%  --h-action  #2450E4   azul de identidad
     54%  --h-sky     #58A9F4   azul claro
     58%              #F69C7E   naranja claro
     100% --h-accent  #F05A28   naranja de Cloudbeach

   El paso calido intermedio es el propio #F05A28 aclarado al 40% de
   blanco, para que el lado tibio sea de un solo tono y no un salto a
   otro color — mismo criterio que ya se habia usado con #F4794F.

   EL PORQUE DE 54/58: azul y naranja son opuestos, asi que cualquier
   cruce entre ellos pasa por un punto neutro. Con las anclas a 48 y 62
   ese punto medido daba #A691A1 — 13% de saturacion, casi 90px de gris
   malva sobre la barra. Los offsets viven en atributos del SVG y no se
   pueden mover por CSS, asi que estan cambiados en cockpit/app.html:
   comprimido a 4 puntos, el neutro es una costura y no una banda, y las
   cinco pisadas se distinguen igual. Se compararon nueve rampas.
   El resto del bloque solo asegura el color de cada parada. */
.chartplotter-svg #budgetCapacityBar stop:nth-child(1) { stop-color: var(--h-ink); }
.chartplotter-svg #budgetCapacityBar stop:nth-child(2) { stop-color: var(--h-action); }
.chartplotter-svg #budgetCapacityBar stop:nth-child(3) { stop-color: var(--h-sky); }
.chartplotter-svg #budgetCapacityBar stop:nth-child(4) { stop-color: #F69C7E; }
.chartplotter-svg #budgetCapacityBar stop:nth-child(5) { stop-color: var(--h-accent); }

.chartplotter-svg #minimalActualStroke stop:nth-child(1) { stop-color: var(--h-ink); }
.chartplotter-svg #minimalActualStroke stop:nth-child(2) { stop-color: var(--h-action); }
.chartplotter-svg #minimalActualStroke stop:nth-child(3) { stop-color: var(--h-sky); }
.chartplotter-svg #minimalActualStroke stop:nth-child(4) { stop-color: #F69C7E; }
.chartplotter-svg #minimalActualStroke stop:nth-child(5) { stop-color: var(--h-accent); }

/* el ultimo verde suelto: el punto de "13 sources monitored" en las
   senales del hero, un <i> a #18A970 puesto a mano. Mismo estado que
   los otros tres indicadores, mismo token. */
.finops-hero-signals i { background-color: var(--h-ok) !important; }

/* ---- 34 · EL TOOLTIP DE AYUDA ESTABA EN OSCURO ---------------
   index.css lo pinta con `background: rgba(3,27,60,.97)` y texto
   #eef6ff: una caja oscura flotando sobre una interfaz clara. Es un
   patron valido en abstracto, pero aca choca por dos motivos concretos:

     1. el globo del bot que montamos —"Need a hand?"— ya es blanco con
        sombra, y los dos son la misma clase de elemento: una capa que
        aparece por encima. Dos tratamientos distintos para lo mismo.
     2. el modo oscuro no esta aprobado (default = LIGHT en la guia),
        asi que no hay razon para que una pieza suelta anticipe ese tema.

   Pasa a superficie clara con el mismo lenguaje que el globo del bot:
   blanco, borde de marca y sombra suave. Contraste del texto: 15.9:1. */
.finops-dashboard .has-tooltip::after {
  background: #FFFFFF !important;
  color: var(--h-ink) !important;
  border: 1px solid var(--h-border) !important;
  box-shadow: 0 10px 26px -8px rgba(10, 30, 70, .34) !important;
  max-width: 280px !important;
  padding: 9px 12px !important;
  border-radius: 12px !important;
  font-weight: 500 !important;
}

/* ---- 35 · EL OTRO SISTEMA DE AYUDA · el "?" y su burbuja ------
   Hay DOS mecanismos de ayuda en la pagina y solo habia arreglado uno.
   Este es el que convierte los parrafos de descripcion en un "?" con
   burbuja — trabajo mio de antes en esta sesion, cuando redujimos la
   prosa — y vive en horizon-skin.css:

     el marcador   ::after con content:"?" a 15x15px y cuerpo de 9.5px
     la burbuja    el propio <p> reposicionado, background #0A1E46,
                   texto blanco, cuerpo 11.5px

   O sea: el "?" era casi la mitad del tamanio del otro icono de ayuda
   (18px) y la burbuja seguia en oscuro aunque ya hubieramos pasado los
   tooltips a claro. Dos piezas del mismo sistema con dos tratamientos.

   Se corrige desde aqui y no en horizon-skin porque esa hoja se
   regenera — es exactamente como se perdio este trabajo una vez. */

/* el marcador: 15 -> 24px, cuerpo 9.5 -> 14px (24 = objetivo de toque) */
.finops-dashboard.finops-dashboard .spend-radar-card h2::after,
.finops-dashboard.finops-dashboard .budgets-panel h2::after,
.finops-dashboard.finops-dashboard div.shadow-xs:has(> div > h3) h3::after,
.finops-dashboard.finops-dashboard div.max-w-3xl > span:first-child::after {
  width: 24px !important;
  height: 24px !important;
  font-size: 14px !important;
  margin-left: 9px !important;
  vertical-align: 0 !important;
}

/* la burbuja: mismo lenguaje que el tooltip y que el globo del bot */
.finops-dashboard.finops-dashboard .spend-radar-card > div:has(h2) > p.text-slate-500,
.finops-dashboard.finops-dashboard .budgets-panel div:has(> h2) > p.text-slate-500,
.finops-dashboard.finops-dashboard div.shadow-xs:has(> div > h3) > div > p.text-xs,
.finops-dashboard.finops-dashboard div.max-w-3xl > p {
  background: #FFFFFF !important;
  color: var(--h-ink) !important;
  border: 1px solid var(--h-border) !important;
  font-size: 14px !important;
  max-width: 300px !important;
  padding: 10px 13px !important;
  border-radius: 12px !important;
  box-shadow: 0 12px 30px -8px rgba(10, 30, 70, .34) !important;
}

/* ---- 36 · LOS DOS ULTIMOS FALLOS DE CONTRASTE -----------------
   Medidos, no supuestos -- y no eran lo que yo habia dicho. No hay
   texto claro sobre superficie clara en el helm; son estos dos:

   1) "+$7.20" en --h-accent-ink sobre una pildora #FFF0ED: 4.20:1.
      El token estaba calculado contra BLANCO (4.65:1) y ahi cumple;
      sobre la pildora tenida el fondo aclara y se cae por debajo de
      4.5. Se corrige en el token, no en la pildora: #C94B21 ->
      #B84018 pasa en las dos superficies (5.53 en blanco, 4.99 en la
      pildora) y evita inventar un segundo "ink para fondo tenido",
      que es justo la proliferacion que veniamos sacando. El token
      solo se usa como color/fill de texto, nunca como relleno, asi
      que oscurecerlo no cambia ninguna superficie.

   2) "Preview correction" en blanco sobre .chartplotter-action, que
      venia con linear-gradient(135deg, #0B71FF, #0757DA). El extremo
      oscuro cumple (6.20:1); el claro no (4.36:1), y el texto cae
      justo encima de el.

      Se pasa a relleno plano var(--h-action): 6.00:1, y de paso se
      va un azul que no era del sistema -- #0B71FF no existe en el
      manual -- y el boton deja de ser el unico CTA con degradado de
      la pantalla. El resto ya son planos en el azul institucional.

   Ninguno de los dos se arregla tocando el markup del cockpit: el
   degradado vive en col/index.css, que es build de la app. */
.finops-dashboard .chartplotter-action,
.finops-dashboard .chartplotter-action:hover {
  background-image: none !important;
  background-color: var(--h-action) !important;
}
.finops-dashboard .chartplotter-action:hover {
  filter: brightness(.93);
}

/* ---- 37 · ESTADO SOBRE LA BARRA NAVY DEL HELM -----------------
   Dos hallazgos que mi primera auditoria no podia ver, porque medía
   el background-COLOR y se saltaba los fondos que son un gradiente.
   Con eso corregido aparecen estos, y los dos son de la misma
   familia: un azul o un fondo pintado por imagen tapando el token.

   1) La barra del helm es navy -- gradient #0A1E46 -> #123072 -- y
      ahi "OFF COURSE", "DRIFT" y "+4.1%" iban en --h-bad-ink
      (#CC002B), que esta calculado contra BLANCO. Sobre el navy da
      2.13:1: el peor contraste de la pantalla, y encima en el texto
      que anuncia el problema.

      No se arregla aclarando el fondo ni oscureciendo el rojo: en
      una superficie oscura el estado necesita su variante clara.
      Es el mismo mecanismo que el manual ya define para el azul
      ("en navy, #2450E4 no pasa -> Sky #58A9F4 toma el rol"), asi
      que el rojo hace lo propio: #FF7285, medido 4.72:1 sobre la
      parada mas clara del gradiente, mismo tono (350 contra 347).

      Todo lo demas de esa barra ya pasaba: blanco 12.42:1, el sky
      del bot 5.80:1, el subtitulo 9.54:1. Fallaba solo el estado.

   2) El MTD activo del selector de periodo: background-color ya era
      var(--h-action) por el trabajo de color, pero encima llevaba
      linear-gradient(135deg, #2585FB, #0864EE), que lo tapa. Blanco
      sobre el extremo claro: 3.60:1. Se quita la imagen y aparece el
      token, 6.00:1 -- y se va otro azul que no es del sistema, el
      tercero de este tipo junto con .chartplotter-action.

   PENDIENTE, y lo dejo anotado en vez de adivinarlo: en esa misma
   barra navy, --h-ok (#1FA95C) daria 4.01:1 si el estado pasa a
   on-course. No lo toco porque no puedo verlo renderizado y no voy
   a inventar el selector de un estado que no medi. --h-warn si pasa
   (5.72:1). */
.finops-dashboard .navigation-helm-bar.is-off-course .helm-status-title,
.finops-dashboard .navigation-helm-bar.is-off-course .helm-drift-label,
.finops-dashboard .navigation-helm-bar.is-off-course .helm-drift-value {
  color: var(--h-bad-on-navy) !important;
}
.finops-dashboard .finops-range-switch button.is-active,
.finops-dashboard .finops-range-switch button[aria-pressed="true"] {
  background-image: none !important;
  background-color: var(--h-action) !important;
}

/* ---- 38 · LA TIRA DE CORRECCION, EN EL NARANJA DE MARCA -------
   Los naranjas de esa tira iban en --h-accent-ink (#B84018), que es
   la variante legible, no el naranja institucional. Pasan a
   var(--h-accent) = #F05A28.

   Se puede hacer aqui y no en el token porque los dos elementos que
   toca aguantan ese naranja:

     $3,746   20px peso 800 -> texto grande (>=18.66px en negrita),
              umbral 3:1, y #F05A28 sobre blanco da 3.40:1. Pasa.
     el punto  es un relleno de 9x9, no texto: sin umbral.

   Lo que NO se toca, y por eso el cambio va aqui y no en el token:

     "CORRECTION REQUIRED" ya estaba en ink navy, no en naranja.
     La etiqueta del chart "MONTH-END FORECAST" mide 11px y a ese
     cuerpo #F05A28 daria 3.40:1 contra un umbral de 4.5. Se queda
     en accent-ink.
     El "+$7.20" de la pildora, por lo mismo.

   Es la razon de ser de los dos tokens: #F05A28 rellena y titula en
   grande, #B84018 se lee en chico. Mover el token habria devuelto
   los fallos de contraste que cerramos hace dos pasos. */
.finops-dashboard .chartplotter-course.is-drifting {
  color: var(--h-accent) !important;
}
.finops-dashboard .chartplotter-course.is-drifting > i {
  background-color: var(--h-accent) !important;
}
.finops-dashboard .chartplotter-overview strong.is-drifting,
.finops-dashboard strong.is-drifting {
  color: var(--h-accent) !important;
}

/* ---- 39 · EL RAIL: BORDE DE MARCA Y LOS DOS ICONOS DEL PIE ----
   Va aqui y no en hrzn-sidebar.css a proposito: esa hoja la comparten
   las seis paginas y esto es solo para FinOps, que es el alcance que
   acordamos. Comprobado con curl: bridge, insights, automations, users
   y settings cargan hrzn-sidebar.css; hrzn-color.css solo la carga
   finops.

   EL BORDE. 2px del naranja institucional en el canto derecho, que es
   el que hace de costura con el contenido. Se hace con un box-shadow
   inset y no con border-right porque la columna del grid mide 220px
   exactos: un borde real depende de que box-sizing sea border-box en
   una hoja que no controlo, y un inset no toca el layout. Verificado
   que .sidebar no tenia box-shadow propio que pisar.

   LOS DOS ICONOS. No estaban roto ninguno de los dos -- lo comprobe
   midiendo, y el desajuste que vi primero (chevrones fuera del rail)
   era un artefacto de la transicion de .26s del grid, no un fallo
   real. Lo que si estaba mal es que no formaban pareja:

     empresa   glifo de 17px dentro de un circulo de 29px
     perfil    iniciales en un circulo macizo de 40px

   Once pixeles de diferencia entre dos fichas que van una encima de
   otra en el mismo bloque. Los dos contenedores pasan a 36px y el
   glifo a 20px, que es la proporcion que ya usan los iconos del nav.
   El chevron del boton de empresa se arregla en el markup: era un
   chevron dentro de un circulo, que es otro icono. */
/* CORRECCION. Lo puse como box-shadow inset y se cortaba a media
   altura. La causa: un inset se pinta encima del fondo del elemento
   pero DEBAJO de su contenido, y .lighthouse-scene tiene fondo opaco
   y llega al canto derecho -- medido, de y=415 a y=635. Ese era el
   tramo que faltaba, justo el del faro.

   Pasa a una franja propia por encima de los hijos. Va absoluta de
   top:0 a bottom:0 contra el rail, que ya es position:fixed y ocupa
   los 860px del alto, asi que cubre el canto entero sin depender de
   ningun hijo. pointer-events:none para que no se coma ningun click. */
.sidebar { position: fixed; }
/* SEGUNDA CORRECCION. La franja recta se salia por los extremos: el
   rail tiene border-radius 0 22px 22px 0, o sea el canto derecho va
   redondeado arriba y abajo, y un rectangulo de 2px pasa de largo por
   fuera de la curva. Eso era lo raro.

   Tampoco sirve redondear la franja: en una caja de 2px de ancho el
   navegador escala los radios al tamanio de la caja, asi que un 22px
   se queda en 1px y no sigue la curva del rail.

   La solucion es que la franja sea del tamanio del rail y el naranja
   sea su BORDE derecho: un borde si sigue el border-radius. Queda un
   trazo de 2px que curva igual que el rail en las dos esquinas, sigue
   por encima de todos los hijos (z-index 20, que era lo que hacia
   falta por el faro) y no toca el layout porque es un pseudo. */
.sidebar::after {
  content: '';
  position: absolute;
  inset: 0;
  border-right: 2px solid var(--h-accent);
  border-radius: 0 22px 22px 0;
  z-index: 20;
  pointer-events: none;
}
.sidebar .profile-avatar {
  width: 36px !important;
  height: 36px !important;
  flex: 0 0 36px !important;
}
.sidebar .profile-avatar { font-size: 13px !important; }
.sidebar .profile-card .chevron svg { width: 18px !important; height: 18px !important; }

/* Y alinearlos, que era la mitad del problema. Las tres fichas del pie
   del rail van apiladas y tenian tres sangrados distintos -- 12px, 8px
   y 16px -- con tres anchos de primera columna distintos. Medido, los
   centros de sus iconos caian en 47, 42 y 41.5: un desfase de 5px en
   una columna de tres elementos, que es de lo que se nota aunque no
   se sepa por que.

   Los tres quedan con el centro en 42: las dos tarjetas con 8px de
   sangrado y 36px de primera columna, y el icono de soporte a 20px
   con su sangrado de 16 (16+16+10 = 42). */
.sidebar .profile-card {
  padding-left: 8px !important;
  grid-template-columns: 36px minmax(0, 1fr) 18px !important;
}
.sidebar .support-link svg { width: 20px !important; height: 20px !important; }

/* ---- 40 · EL WORDMARK REAL EN EL RAIL -------------------------
   Sacado de /demohorizon/2050/: ahi el logo no es el SVG inline que
   trae el markup -- ese esta oculto -- sino un PNG que se pone como
   fondo de .h-brand::before a 132x40. Hay dos versiones y la que
   corresponde aqui es la de FONDO OSCURO, que es el arte en blanco,
   porque nuestro rail es navy #011A3B. Es el mismo wordmark: el arco
   y las letras, 446x134 con transparencia.

   Solo en el rail EXPANDIDO. Colapsado el rail mide 76px y el logo
   pide 132; ahi se queda el monograma "H" en su caja de 35px, que ya
   estaba resuelto en hrzn-sidebar.css y es la solucion correcta para
   ese ancho.

   El texto "HRZN" no se borra del DOM, se pasa a font-size 0: el
   <a> ya lleva aria-label, y dejarlo mantiene el elemento por si la
   imagen no carga. "FINOPS" se queda debajo -- el logo dice el
   producto, esa linea dice la seccion. */
html[data-sidebar="expanded"] .sidebar .brand span {
  display: block !important;
  width: 132px !important;
  height: 40px !important;
  background: url('../img/horizon-logo-dark.png') left center / contain no-repeat !important;
  font-size: 0 !important;
  transform: none !important;
  border: 0 !important;
}
html[data-sidebar="expanded"] .sidebar .brand span::before,
html[data-sidebar="expanded"] .sidebar .brand span::after {
  display: none !important;
}

/* Y alinearlo. El bloque de marca tenia padding 0 40px, mientras que
   TODO lo demas del rail arranca en x=16: el boton de colapsar y las
   seis fichas del nav. El logo y "FINOPS" quedaban 24px mas a la
   derecha que la columna que forman los demas. Pasa a 16. */
html[data-sidebar="expanded"] .sidebar .brand {
  padding-left: 16px !important;
  padding-right: 16px !important;
}

/* ---- 41 · EL ACTIVO DEL NAV -----------------------------------
   Dos pedidos que se pisan, y hay que resolverlo con numeros:
   "que no se vea ese violeta" y "que el texto siga blanco".

   Medido antes de tocar: el pill YA era #2450E4 -- matiz 226, que es
   --h-action, el azul del manual -- y el barrido no encontro un solo
   elemento violeta en el rail. Lo que lo hacia leer violeta era el
   relleno macizo al 84% de saturacion sobre navy; el mismo azul sobre
   blanco no da esa lectura.

   Primero lo pase a Sky #58A9F4 macizo, que es lo que el manual manda
   para superficies oscuras. Pero Sky macizo NO admite texto blanco:
   da 2.53:1 contra un minimo de 4.5. Con texto blanco obligatorio, un
   relleno macizo claro queda descartado por contraste.

   Asi que Sky va como INDICADOR y no como relleno: barra solida de
   3px a la izquierda y fondo tenue al 18%. El texto queda blanco sobre
   ese fondo tenue, que mezclado con el navy da rgb(17,52,92) --
   contraste 12.59:1. Cumple las dos cosas: nada de violeta, texto
   blanco, y encima es mas calmo, que es la restriccion del manual
   ("un focal point por vista"; un bloque saturado en el rail competia
   con el contenido). */
.bridge-page .sidebar .side-link.is-active,
.bridge-page .sidebar .side-link.is-active:hover,
.bridge-page .sidebar .side-link.is-active:focus-visible {
  background: rgba(88, 169, 244, .18) !important;
  background-image: none !important;
  color: #FFFFFF !important;
  position: relative !important;
  box-shadow: inset 3px 0 0 0 var(--h-accent) !important;   /* naranja de marca */
}
.bridge-page .sidebar .side-link.is-active b,
.bridge-page .sidebar .side-link.is-active .hz-ico,
.bridge-page .sidebar .side-link.is-active svg {
  color: #FFFFFF !important;
  stroke: #FFFFFF !important;
}

/* ---- 42 · EL PIE DEL RAIL: UN SOLO TRATAMIENTO ----------------
   Cuatro filas y no coincidia casi nada. Medido:

     fila              alto  fondo         borde  icono
     Light theme        34   blanco 5.5%   si     svg 15, sin circulo
     Acme Corp.         68   navy 54%      si     circulo 36 perfilado
     Help & Support     55   transparente  no     svg 20, sin circulo
     M. Smith           57   transparente  no     circulo 36 MACIZO azul

   Sangrados 12 / 8 / 16 / 8. Dos con caja y dos sin. Un icono en
   circulo fino y otro en circulo macizo saturado. Cuatro maneras de
   decir "fila del pie del rail" en cuatro filas seguidas: de ahi que
   se vea raro, aunque cada una por separado este bien.

   Quedan las cuatro con la misma caja -- que es el tratamiento que ya
   tenian dos de ellas --, el mismo sangrado de 8px y el hueco de icono
   de 36px, para que los cuatro iconos caigan en el mismo centro (42,
   el que ya habiamos alineado). Alto 44 las de una linea y 56 las de
   dos; suman 224px contra los 222 que ocupaba el bloque, asi que no
   empuja nada.

   LA TIPOGRAFIA. Aparecio un agujero de fondo: los textos estaban a
   10, 10.5 y 12px. Todo hrzn-type.css esta scopeado a
   .finops-dashboard, y eso vive DENTRO del iframe -- el rail es del
   shell, asi que nunca le llego el sistema. Aqui va el minimo: 14px
   la linea principal, 12px la secundaria. No es la escala completa,
   pero saca al rail de tamanios que no se leen.

   LA INSIGNIA. Era un circulo macizo #2450E4 sobre navy, o sea
   exactamente el caso que hacia leer violeta al activo del nav. Pasa
   a Sky con iniciales en navy, igual que el activo: 5.79:1. */
.sidebar .side-bottom > * {
  min-height: 44px !important;
  padding: 8px !important;
  margin: 0 0 8px !important;
  border-radius: 10px !important;
  background: rgba(255, 255, 255, .05) !important;
  border: 1px solid rgba(174, 210, 255, .16) !important;
  box-sizing: border-box !important;
}
.sidebar .side-bottom > *:last-child { margin-bottom: 0 !important; }
.sidebar .side-bottom > *:hover { background: rgba(255, 255, 255, .10) !important; }

/* min-height solo pone un piso; el contenido seguia mandando y las
   alturas quedaron en 44 / 68 / 55 / 62, o sea seguian siendo cuatro.
   Se fijan por TIPO de fila: 48 las de una linea, 64 las de dos. */
/* Iba agrupada con .sidebar .hz-theme-toggle. Se quito ESE selector
   y no la regla: .support-link sigue vivo y sigue necesitando su
   altura de 48. */
.sidebar .support-link {
  height: 48px !important;
  min-height: 48px !important;
}
.sidebar .profile-card {
  height: 64px !important;
  min-height: 64px !important;
}

/* el hueco de icono de las dos filas que no son tarjeta: 8 de sangrado
   + 8 de margen + 20 de icono deja el centro en 42, el mismo que el
   slot de 36px de las tarjetas */
/* El icono pasa de 20 a 21px para que TODO el rail use la misma
   medida: .sidebar .hz-ico ya define 21px en hrzn-sidebar.css, la
   hoja que cargan las diez paginas con rail. Antes convivian TRES
   tamanos para este mismo icono, segun que hojas cargaba cada
   pagina: 19px (horizon-pages / horizon-skin), 20px (aca) y 21px
   (las que no cargaban ninguna de las dos).

   El margen izquierdo baja 8 -> 7.5 para que el EJE del icono no se
   mueva: antes 8 + 20/2 = 18, ahora 7.5 + 21/2 = 18. Identico.

   OJO: el margen derecho NO se toca aca. Lo fija mas abajo, en esta
   misma hoja, `.sidebar .support-link svg { margin-right: ... }` --
   misma especificidad y mas tarde, asi que gana esa. Ahi baja de 6
   a 5.5 por la misma razon: 7.5 + 21 + 5.5 = 34, el mismo bloque
   que daba 8 + 20 + 6, para que el texto siga arrancando donde
   arranca el nombre del perfil.

   (El comentario que estaba aca antes hablaba de un bloque de 36px.
   No era cierto desde que se agrego la regla de mas abajo: el
   bloque real era 8 + 20 + 6 = 34.)

   El selector de .hz-theme-toggle se fue con el componente. */
.sidebar .support-link svg {
  width: 21px !important;
  height: 21px !important;
  margin-left: 7.5px !important;
}

.sidebar .side-bottom b { font-size: 14px !important; }
.sidebar .side-bottom small { font-size: 12px !important; }

/* OJO CON LA GUARDA.
   ------------------------------------------------------------
   "Help & Support" es la UNICA etiqueta del rail que es un nodo de
   texto suelto: no esta envuelta en <b> ni en <span>, asi que no hay
   elemento al que ponerle display:none. Por eso hrzn-sidebar.css la
   apaga con `font-size: 0` cuando el rail esta colapsado.

   Este !important estaba SIN guarda y se lo comia: la palabra
   sobrevivia al colapso y desbordaba el rail de 76px -- el texto
   medido ocupaba 45x19px dentro de un boton de 60px, y se partia en
   dos lineas encima del icono.

   La guarda es la misma que hrzn-type-system.css:110 ya usa para
   esta misma regla. Si se toca una, tocar la otra.

   El icono no se ve afectado: .sidebar .support-link svg de mas
   arriba lo fija en 20px con !important, asi que no depende del
   font-size del boton.

   Los selectores de .hz-theme-toggle se fueron con el componente:
   ese conmutador ya no existe en ninguna pagina. */
:root:not([data-sidebar="collapsed"]) .sidebar .support-link { font-size: 14px !important; }

.sidebar .profile-avatar {
  background: var(--h-sky, #58A9F4) !important;
  color: var(--h-ink) !important;
}

/* ---- 43 · EL PIE DEL RAIL, SEGUNDA PASADA ---------------------
   Se afina lo de la seccion 42, que igualo las cuatro filas con caja.
   Ahora la caja se queda SOLO en el conmutador de tema y las otras
   tres van limpias.

   Tiene sentido y no es una inconsistencia: son dos cosas distintas.
   El tema es un CONTROL -- se pulsa y cambia algo al instante -- y las
   otras tres son FILAS DE MENU que abren algo. Un control se dibuja
   como boton; una fila de menu no necesita caja, le basta el hover.

   El conmutador se queda solo con el icono, en un boton de 40x40. El
   texto "Light theme" no se borra del DOM, se oculta: el boton lleva
   aria-label, asi que sigue anunciandose. Y 40px es objetivo de toque
   comodo, que un icono suelto de 20px no daba.

   Las tres filas conservan alto e hueco de icono de la pasada
   anterior: el ritmo vertical y la columna en 43 siguen valiendo, lo
   que se va es la caja. */
.sidebar .side-bottom > .support-link,
.sidebar .side-bottom > .profile-card {
  background: transparent !important;
  border-color: transparent !important;
  border-width: 0 !important;
}
.sidebar .side-bottom > .support-link:hover,
.sidebar .side-bottom > .profile-card:hover {
  background: rgba(255, 255, 255, .07) !important;
}

/* Aca vivian las reglas del conmutador de tema (tamano del boton,
   ocultado de su etiqueta y escalado de los dos SVG apilados). Se
   fueron enteras con el componente: eran suyas y de nadie mas. */

/* ---- 44 · REMATE DE LAS BARRAS Y DOS AJUSTES DEL RAIL ---------
   LAS BARRAS. Cada una llevaba una pildora blanca de 8px pegada al
   extremo derecho (absolute right-0 w-2 bg-white/60): un falso brillo
   de borde de ahi la terminacion rara -- el overflow:hidden del padre
   la corta contra la punta redondeada, asi que en la barra al 100%
   quedaba como una muesca. Y va contra la regla de data-viz del
   manual: rellenos planos, sin brillos ni sombras sobre datos. Se
   quita y la barra termina en su propio radio.

   ENTERPRISE PLAN. Se elimino la ficha entera del rail; el parrafo
   que describia su icono y su columna de 36px se fue con ella.

   CONMUTADOR DE TEMA. Tambien eliminado. Aca estaba su circulo
   blanco con el icono en el navy del rail. */
.finops-dashboard .systems-load-card .h-full > div { display: none !important; }

/* La ficha de Acme Corp. / Enterprise plan se elimino del rail por
   pedido. Con ella se fueron sus reglas: ya no quedaba nada a lo que
   aplicaran y dejarlas habria sido codigo muerto apuntando a un
   selector inexistente. .profile-card conserva las suyas -- estaban
   agrupadas con las de company-card, asi que se separaron en vez de
   borrarlas. */

/* ---- 45 · LA FICHA DE PERFIL ----------------------------------
   Nombre a Alan Gucovschi, y la insignia pasa de iniciales a foto.

   La foto va como <img> dentro del circulo y las iniciales quedan
   DEBAJO en un <i>, no borradas: si la imagen no carga -- y mientras
   no este subida -- se ve el circulo Sky con "AG" en navy, que es el
   estado que ya teniamos y sigue midiendo 6.52:1. Asi la ficha nunca
   queda vacia ni muestra el icono roto del navegador.

   object-position 50% 25% porque en un retrato recortado a circulo el
   centro geometrico cae sobre la boca; subir el encuadre deja la cara
   centrada. */
.sidebar .profile-avatar {
  position: relative !important;
  overflow: hidden !important;
  display: grid !important;
  place-items: center !important;
}
.sidebar .profile-avatar > i {
  grid-area: 1 / 1;
  font-style: normal;
  font-size: 13px;
  font-weight: 700;
  color: var(--h-ink);
}
.sidebar .profile-avatar > img {
  grid-area: 1 / 1;
  width: 100% !important;
  height: 100% !important;
  object-fit: cover;
  border-radius: 50%;
  z-index: 1;
  /* la fuente es 1:1 y el circulo tambien, asi que cover no recorta y
     object-position no hace nada -- se veia el cuadrado entero, hombros
     incluidos, y a 36px la cara quedaba chica. El encuadre se hace con
     transform: escala para acercar, y 4% hacia abajo porque el centro
     de la cabeza cae sobre el 40% de la altura, por encima del centro
     geometrico de la foto. */
  transform: scale(1.22) translateY(4%);
}

/* ---- 46 · LA FICHA DE PERFIL, AJUSTE FINAL --------------------
   Foto mas grande, fuera el chevron y fuera "Owner".

   La foto a 44px. El sangrado baja de 8 a 4 para que el centro del
   circulo caiga en 42, el mismo eje que el icono de tema y el de
   Help & Support: son tres marcas apiladas y su columna se nota mas
   que dos pixeles en el texto.

   El chevron sale del grid, no solo de la vista: se pasa a dos
   columnas. Si se dejara con display:none la tercera columna de 18px
   seguiria reservada y el nombre no ganaria el sitio -- y lo
   necesitaba, porque "Alan Gucovschi" no entraba en los 102px que
   quedaban y partia en dos lineas.

   Sin "Owner" la fila es de una sola linea, asi que baja de 64 a 56.
   Las iniciales de reserva suben a 15px para acompaniar al circulo. */
.sidebar .profile-avatar {
  width: 44px !important;
  height: 44px !important;
  flex: 0 0 44px !important;
}
.sidebar .profile-avatar > i { font-size: 15px !important; }
.sidebar .profile-card {
  grid-template-columns: 44px minmax(0, 1fr) !important;
  padding-left: 4px !important;
  height: 56px !important;
  min-height: 56px !important;
}
.sidebar .profile-card .chevron { display: none !important; }
.sidebar .profile-card small { display: none !important; }

/* Los dos textos del pie quedaban a 74 y 72: Help & Support y el
   nombre van uno debajo del otro, y en una columna de texto apilada
   dos pixeles se ven. El icono de soporte cede margen derecho y los
   dos arrancan en 72. Los ejes de los tres iconos siguen en 42.

   Era 6px cuando el icono media 20. Al unificarlo en 21 (ver la
   regla de arriba) baja a 5.5 para que el bloque siga midiendo 34
   y el texto no se corra: 7.5 + 21 + 5.5 = 8 + 20 + 6 = 34. */
.sidebar .support-link svg { margin-right: 5.5px !important; }
