/* Tokens visuales institucionales (Etapa 3 del rediseño, ver docs/ARQUITECTURA.md).
   Redefinir las variables de Bootstrap 5.3 recolorea automáticamente los
   utilitarios .bg-*, .text-*, .border-*, .text-bg-* (badges) en toda la
   aplicación sin editar cada plantilla -- verificado contra el CSS compilado
   real de bootstrap@5.3.3.

   Verificado también que .btn-* y .alert-* NO heredan de estas variables:
   Bootstrap "hornea" un color hexadecimal fijo por componente en tiempo de
   compilación (--bs-btn-bg, --bs-alert-bg, etc.), no una referencia en vivo
   a --bs-primary/--bs-warning/etc. Como son los patrones más usados de la
   app (botones en los 281 formularios, alertas flash en cada página), se
   sobrescriben aparte más abajo, con los mismos tokens como única fuente de
   los colores base para no duplicar valores. */
:root {
  /* Tokens propios de la plataforma. Prefijo --app-* (antes --ai-*, de
     AUDINTUS); los alias --ai-* se conservan una versión de transición para
     no romper referencias no detectadas. */
  --app-nav-bg: #0B1F5B;          /* azul de navegación, derivado del azul de marca #072190 */
  --app-nav-bg-soft: #EAF0F5;

  /* Paleta GINOP. El azul de marca es #072190 (contraste ~13.7:1 sobre
     blanco: AA/AAA para texto y para botón sólido con texto blanco). */
  --bs-primary: #072190;      --bs-primary-rgb: 7, 33, 144;
  --bs-info: #2F6F9F;         --bs-info-rgb: 47, 111, 159;
  --bs-success: #2E7D5B;      --bs-success-rgb: 46, 125, 91;
  --bs-warning: #A65D03;      --bs-warning-rgb: 166, 93, 3;
  --bs-danger: #B42318;       --bs-danger-rgb: 180, 35, 24;
  --bs-body-color: #1F2937;
  --bs-secondary-color: #667085;
  --bs-body-bg: #F5F7FA;
  --bs-border-color: #D8DEE6;
  --bs-border-radius: 0.5rem;
  --bs-border-radius-sm: 0.375rem;

  /* Amarillo de acento de la marca (medido del arte de GINOP_logo.png). NO
     usar como color de texto sobre fondo claro (no llega a 4.5:1): reservado
     para indicadores/estados de atención y como fondo con
     --app-brand-accent-contrast encima (#1F2937 sobre este amarillo da ~11:1). */
  --app-brand-accent: #F8D000;
  --app-brand-accent-contrast: #1F2937;

  /* "Riesgo muy alto" no tiene equivalente en la paleta semántica de 5
     colores de Bootstrap -- variable propia, consumida por status_badge(). */
  --app-riesgo-muy-alto: #7A1A14;
  --app-riesgo-muy-alto-bg: #F9E2E0;

  /* Alias de transición (--ai-* -> --app-*). Eliminar en una versión futura. */
  --ai-nav-bg: var(--app-nav-bg);
  --ai-nav-bg-soft: var(--app-nav-bg-soft);
  --ai-riesgo-muy-alto: var(--app-riesgo-muy-alto);
  --ai-riesgo-muy-alto-bg: var(--app-riesgo-muy-alto-bg);
}

:focus-visible {
  outline: 2px solid var(--bs-primary);
  outline-offset: 2px;
}
/* Sobre superficies oscuras (nav #0B1F5B, botones sólidos) el anillo azul no
   se ve -- usar uno claro. */
#sidebar :focus-visible,
.btn-primary:focus-visible,
.btn-success:focus-visible,
.btn-danger:focus-visible,
.btn-info:focus-visible,
.btn-warning:focus-visible {
  outline-color: #fff;
  outline-offset: 2px;
}
/* Enlace "saltar al contenido" -- solo visible al recibir foco por teclado. */
.skip-link {
  position: absolute;
  left: 8px;
  top: -60px;
  z-index: 1080;
  padding: 0.5rem 0.9rem;
  background: var(--bs-primary);
  color: #fff;
  border-radius: 0 0 var(--bs-border-radius-sm) var(--bs-border-radius-sm);
  transition: top .15s ease-in-out;
}
.skip-link:focus { top: 0; color: #fff; }

/* Botones sólidos y outline -- únicos consumidores reales de --bs-btn-bg,
   que Bootstrap no deriva de --bs-primary/etc. (ver nota arriba). Solo se
   sobrescriben los 5 colores que la app usa de verdad como flash/acción
   (confirmado con grep sobre app/blueprints: danger, warning, success, info
   -- 'primary' se usa para Guardar/Crear vía btn-primary). */
.btn-primary {
  --bs-btn-bg: var(--bs-primary); --bs-btn-border-color: var(--bs-primary);
  --bs-btn-hover-bg: #061a78; --bs-btn-hover-border-color: #061a78;
  --bs-btn-active-bg: #04125e; --bs-btn-active-border-color: #04125e;
  --bs-btn-disabled-bg: var(--bs-primary); --bs-btn-disabled-border-color: var(--bs-primary);
  --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}
.btn-outline-primary {
  --bs-btn-color: var(--bs-primary); --bs-btn-border-color: var(--bs-primary);
  --bs-btn-hover-bg: var(--bs-primary); --bs-btn-hover-border-color: var(--bs-primary);
  --bs-btn-active-bg: var(--bs-primary); --bs-btn-active-border-color: var(--bs-primary);
  --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}
.btn-success {
  --bs-btn-bg: var(--bs-success); --bs-btn-border-color: var(--bs-success);
  --bs-btn-hover-bg: #286e50; --bs-btn-hover-border-color: #286e50;
  --bs-btn-active-bg: #246247; --bs-btn-active-border-color: #246247;
  --bs-btn-disabled-bg: var(--bs-success); --bs-btn-disabled-border-color: var(--bs-success);
  --bs-btn-focus-shadow-rgb: var(--bs-success-rgb);
}
.btn-outline-success {
  --bs-btn-color: var(--bs-success); --bs-btn-border-color: var(--bs-success);
  --bs-btn-hover-bg: var(--bs-success); --bs-btn-hover-border-color: var(--bs-success);
  --bs-btn-active-bg: var(--bs-success); --bs-btn-active-border-color: var(--bs-success);
  --bs-btn-focus-shadow-rgb: var(--bs-success-rgb);
}
.btn-warning {
  --bs-btn-color: #fff; --bs-btn-bg: var(--bs-warning); --bs-btn-border-color: var(--bs-warning);
  --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #925203; --bs-btn-hover-border-color: #925203;
  --bs-btn-active-color: #fff; --bs-btn-active-bg: #814902; --bs-btn-active-border-color: #814902;
  --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: var(--bs-warning); --bs-btn-disabled-border-color: var(--bs-warning);
  --bs-btn-focus-shadow-rgb: var(--bs-warning-rgb);
}
.btn-outline-warning {
  --bs-btn-color: var(--bs-warning); --bs-btn-border-color: var(--bs-warning);
  --bs-btn-hover-color: #fff; --bs-btn-hover-bg: var(--bs-warning); --bs-btn-hover-border-color: var(--bs-warning);
  --bs-btn-active-color: #fff; --bs-btn-active-bg: var(--bs-warning); --bs-btn-active-border-color: var(--bs-warning);
  --bs-btn-focus-shadow-rgb: var(--bs-warning-rgb);
}
.btn-danger {
  --bs-btn-bg: var(--bs-danger); --bs-btn-border-color: var(--bs-danger);
  --bs-btn-hover-bg: #9e1f15; --bs-btn-hover-border-color: #9e1f15;
  --bs-btn-active-bg: #8c1b13; --bs-btn-active-border-color: #8c1b13;
  --bs-btn-disabled-bg: var(--bs-danger); --bs-btn-disabled-border-color: var(--bs-danger);
  --bs-btn-focus-shadow-rgb: var(--bs-danger-rgb);
}
.btn-outline-danger {
  --bs-btn-color: var(--bs-danger); --bs-btn-border-color: var(--bs-danger);
  --bs-btn-hover-bg: var(--bs-danger); --bs-btn-hover-border-color: var(--bs-danger);
  --bs-btn-active-bg: var(--bs-danger); --bs-btn-active-border-color: var(--bs-danger);
  --bs-btn-focus-shadow-rgb: var(--bs-danger-rgb);
}
.btn-info {
  --bs-btn-color: #fff; --bs-btn-bg: var(--bs-info); --bs-btn-border-color: var(--bs-info);
  --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #29628c; --bs-btn-hover-border-color: #29628c;
  --bs-btn-active-color: #fff; --bs-btn-active-bg: #25577c; --bs-btn-active-border-color: #25577c;
  --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: var(--bs-info); --bs-btn-disabled-border-color: var(--bs-info);
  --bs-btn-focus-shadow-rgb: var(--bs-info-rgb);
}
.btn-outline-info {
  --bs-btn-color: var(--bs-info); --bs-btn-border-color: var(--bs-info);
  --bs-btn-hover-color: #fff; --bs-btn-hover-bg: var(--bs-info); --bs-btn-hover-border-color: var(--bs-info);
  --bs-btn-active-color: #fff; --bs-btn-active-bg: var(--bs-info); --bs-btn-active-border-color: var(--bs-info);
  --bs-btn-focus-shadow-rgb: var(--bs-info-rgb);
}

/* Alertas flash -- las 4 categorías que la app usa de verdad (confirmado con
   grep: danger/warning/success/info, nunca 'primary'). Mismos tonos "fondo
   suave" ya aprobados en la sección 6.2 de la propuesta visual. */
.alert-success { --bs-alert-color: #1c4f3a; --bs-alert-bg: #E8F4EE; --bs-alert-border-color: #cfe9dc; }
.alert-warning { --bs-alert-color: var(--bs-warning); --bs-alert-bg: #FFF4E0; --bs-alert-border-color: #ffe4b3; }
.alert-danger  { --bs-alert-color: var(--bs-danger);  --bs-alert-bg: #FDECEC; --bs-alert-border-color: #f8cfcf; }
.alert-info    { --bs-alert-color: var(--bs-info);    --bs-alert-bg: #E8F4FA; --bs-alert-border-color: #cfe6f2; }

/* Badges "bg-warning text-dark" (Etapa 9, ~40 usos en 25 plantillas) --
   convención correcta con el amarillo brillante por defecto de Bootstrap
   (#ffc107), pero --bs-warning ahora es un ámbar oscuro (#A65D03, Etapa 3) y
   con ese fondo el texto oscuro da ~2.9:1 de contraste (mínimo exigible
   4.5:1) -- prácticamente ilegible. Blanco sobre el mismo fondo da 5.0:1. Se
   corrige centralizado aquí en vez de tocar cada plantilla; no afecta
   bg-warning sin text-dark (poco común, casi siempre van juntos). */
.badge.bg-warning.text-dark {
  color: #fff !important;
}
/* Mismo problema y misma solución para "bg-info text-dark" (13 plantillas +
   la fila "Enviado" de cat_estatus_programa, clase_bootstrap en BD): con
   --bs-info oscurecido (#2F6F9F, Etapa 3) el texto oscuro da ~2.7:1. */
.badge.bg-info.text-dark {
  color: #fff !important;
}

/* Sidebar -- color de navegación propio (--app-nav-bg), distinto
   del bg-dark genérico de Bootstrap que se sigue usando en otras partes de la
   app -- no se toca --bs-dark para no recolorear elementos ajenos al menú. */
#sidebar, #sidebarOffcanvas {
  background-color: var(--app-nav-bg) !important;
}
/* .text-muted de Bootstrap resuelve a var(--bs-secondary-color) (#667085),
   un gris pensado para fondos claros -- sobre el fondo azul marino oscuro
   del sidebar (--app-nav-bg) da un contraste real de ~2.6:1 (mínimo exigible
   4.5:1), por eso "JMM" y el nombre/rol del usuario en el pie del menú se
   veían casi invisibles. Se sobrescribe solo dentro de #sidebar, sin tocar
   --bs-secondary-color (se usa correctamente en el resto de la app, sobre
   fondos claros). */
#sidebar .text-muted {
  color: rgba(255,255,255,0.6) !important;
}

/* Sidebar -- ancho por defecto (menú plano de área externa, sin cambios) */
#sidebar {
  min-height: 100vh;
  width: 240px;
  min-width: 240px;
  transition: width 0.2s ease;
  overflow-y: auto;
  overflow-x: hidden;
}
#sidebar.collapsed {
  width: 0;
  min-width: 0;
}
#sidebar .nav-link {
  font-size: 0.85rem;
  padding: 0.4rem 1rem;
  border-radius: 0;
}
#sidebar .nav-link:hover,
#sidebar .nav-link.active {
  background-color: rgba(255,255,255,0.1);
}
.sidebar-header {
  min-height: 56px;
}

/* Identidad GINOP (isotipo/logotipo, ver docs/ARQUITECTURA.md). El isotipo
   (G_INOP_logo.png, la "G") va sobre el fondo oscuro del sidebar dentro de un
   contenedor claro para no perderse; nunca se le aplica un filtro CSS para
   volverlo blanco, porque altera los colores de la marca. */
.app-brand-mark {
  width: 36px;
  height: 36px;
  object-fit: contain;
  background-color: var(--app-nav-bg-soft, #fff);
  border-radius: 0.375rem;
  padding: 4px;
  flex-shrink: 0;
}
.app-brand-name {
  letter-spacing: 0.02em;
}
.app-version {
  display: block;
  font-size: 0.7rem;
}
.login-brand-logo {
  max-width: 220px;
  width: 100%;
  height: auto;
  object-fit: contain;
}

/* Sidebar -- roles internos: riel de íconos (uno por pilar) + panel del
   pilar activo. Ancho fijo = riel (56px) + panel (200px). */
#sidebar.sidebar-riel {
  width: 256px;
  min-width: 256px;
  overflow: visible;
}
#sidebar-rail {
  width: 56px;
  min-width: 56px;
  background-color: rgba(0,0,0,0.15);
  overflow-y: auto;
}
#sidebar-rail .rail-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 48px;
  color: #adb5bd;
  background: none;
  border: none;
  border-left: 3px solid transparent;
  font-size: 1.15rem;
  text-decoration: none;
}
#sidebar-rail .rail-btn:hover {
  color: #fff;
  background-color: rgba(255,255,255,0.06);
}
#sidebar-rail .rail-btn.active {
  color: #fff;
  border-left-color: #0d6efd;
  background-color: rgba(255,255,255,0.08);
}
#sidebar-panel {
  width: 200px;
  min-width: 200px;
  overflow-y: auto;
  transition: width 0.2s ease;
}
/* El estado "colapsado" vive en #sidebar (fuente única, toggleado por
   main.js), no en #sidebar-panel -- así una sola clase controla el ancho
   total del sidebar, el panel Y el encabezado (nombre/leyenda ocultos,
   deja solo el logo), en vez de que el panel se vacíe sin que el
   contenedor exterior de ancho fijo (.sidebar-riel) se achique con él. */
#sidebar.sidebar-riel {
  transition: width 0.2s ease;
}
#sidebar.sidebar-riel.colapsado {
  width: 56px;
  min-width: 56px;
}
#sidebar.sidebar-riel.colapsado #sidebar-panel {
  width: 0;
  min-width: 0;
  overflow: hidden;
}
#sidebar.sidebar-riel.colapsado .sidebar-header {
  padding-left: .5rem;
  padding-right: .5rem;
  justify-content: center;
}
#sidebar.sidebar-riel.colapsado .app-brand-name,
#sidebar.sidebar-riel.colapsado .app-brand-descriptor,
#sidebar.sidebar-riel.colapsado .app-brand-tagline {
  display: none;
}
#sidebar-panel .panel-pilar {
  display: none;
}
#sidebar-panel .panel-pilar.activo {
  display: block;
}
#sidebar-panel .panel-pilar-titulo {
  font-size: 0.65rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
#sidebar-panel .nav-link {
  font-size: 0.85rem;
  padding: 0.4rem 1rem;
  border-radius: 0;
  display: flex;
  align-items: center;
}
#sidebar-panel .nav-link:hover,
#sidebar-panel .nav-link.active {
  background-color: rgba(255,255,255,0.1);
}
#sidebar-panel .badge {
  font-size: 0.65rem;
  margin-left: auto;
}
#sidebarBuscar {
  background-color: rgba(255,255,255,0.08);
  color: #fff;
  border-color: rgba(255,255,255,0.15);
}
#sidebarBuscar::placeholder {
  color: #adb5bd;
}

/* Por debajo de 768px, tanto el riel+panel (roles internos) como el sidebar
   plano (área externa) desaparecen -- la navegación ocurre en
   #sidebarOffcanvas (ambas variantes lo definen, ver sidebar.html). */
@media (max-width: 767.98px) {
  #sidebar.sidebar-riel,
  #sidebar.sidebar-externo {
    width: 0;
    min-width: 0;
    overflow: hidden;
    border: none;
  }
}

/* Offcanvas + acordeón para pantallas chicas -- tema oscuro sobre el
   accordion de Bootstrap (por defecto trae fondo claro/texto oscuro). */
#sidebarOffcanvas .accordion-button {
  --bs-accordion-btn-color: #fff;
  --bs-accordion-btn-bg: transparent;
  --bs-accordion-active-color: #fff;
  --bs-accordion-active-bg: rgba(255,255,255,0.08);
  --bs-accordion-border-color: rgba(255,255,255,0.15);
  box-shadow: none;
}
#sidebarOffcanvas .accordion-button::after {
  filter: invert(1) grayscale(1) brightness(2);
}
#sidebarOffcanvas .accordion-item {
  background-color: transparent;
  border-color: rgba(255,255,255,0.15);
}
#sidebarOffcanvas .nav-link {
  font-size: 0.9rem;
  padding: 0.45rem 1.25rem;
  display: flex;
  align-items: center;
}
#sidebarOffcanvas .nav-link:hover,
#sidebarOffcanvas .nav-link.active {
  background-color: rgba(255,255,255,0.1);
}
#sidebarOffcanvas .badge {
  font-size: 0.65rem;
  margin-left: auto;
}
#sidebarBuscarMovil {
  background-color: rgba(255,255,255,0.08);
  color: #fff;
  border-color: rgba(255,255,255,0.15);
}
#sidebarBuscarMovil::placeholder {
  color: #adb5bd;
}

/* Page content -- min-width:0 evita que el contenido empuje el ancho del
   documento completo (causa real del scroll horizontal en móvil); el
   desbordamiento de tablas anchas se resuelve de forma localizada con
   table-responsive (Etapa 6), no cortando toda la página con overflow:hidden
   como antes -- eso hacía inalcanzables columnas/acciones en pantallas chicas. */
#page-content {
  min-height: 100vh;
  min-width: 0;
  background-color: var(--bs-body-bg);
}
#wrapper {
  min-height: 100vh;
}

/* Tables */
.table-hover tbody tr:hover { background-color: rgba(13,110,253,0.05); }
.table th { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em; }
.table td { font-size: 0.875rem; vertical-align: middle; }

/* Badges de nivel de riesgo -- consumidas por status_badge() en
   components/ui.html (Etapa 4). Antes definidas pero sin ningún consumidor
   real en las plantillas (0 usos confirmados); ahora usan los tokens de la
   Etapa 3 en vez de los colores fijos originales. "Alto" y "Medio" quedan
   por fin distinguibles entre sí (antes ambos caían en tonos amarillo/naranja
   parecidos en varias plantillas). */
.badge-nivel-muy-alto { background-color: var(--app-riesgo-muy-alto) !important; color: #fff !important; }
.badge-nivel-alto     { background-color: var(--bs-danger) !important; color: #fff !important; }
.badge-nivel-medio    { background-color: var(--bs-warning) !important; color: #fff !important; }
.badge-nivel-bajo     { background-color: var(--bs-success) !important; color: #fff !important; }

/* Progress bar */
.progress { height: 8px; }

/* Forms */
.form-label { font-size: 0.85rem; font-weight: 500; }
textarea.form-control { min-height: 80px; }

/* Texto libre con saltos de línea reales (descripción de ítems de
   Requerimientos, justificaciones, comentarios de revisión) -- por defecto
   el HTML colapsa los saltos de línea guardados en la base de datos; esta
   clase los respeta al mostrarlos, sin modificar el texto guardado. */
.texto-preservar-lineas { white-space: pre-line; }

/* Tarjeta con hover -- antes definida inline en catalogos/index.html (uno de
   los 4 <style> propios señalados en el diagnóstico); movida aquí para
   reusarse donde haga falta y para heredar el token --bs-primary en vez de
   un azul fijo. */
.card-hover {
  transition: border-color .15s, background .15s;
}
.card-hover:hover {
  border-color: var(--bs-primary);
  background: var(--app-nav-bg-soft);
}

/* Tarjeta de módulo/dominio del centro de trabajo (macro module_card en
   components/ui.html, Etapa 3 de GINOP). Borde izquierdo con el primario
   (contraste amplio); la tarjeta ya queda delimitada por su sombra. */
.app-module-card {
  border-left: 3px solid var(--bs-primary) !important;
  transition: transform .12s ease, box-shadow .12s ease;
}
.app-module-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 .5rem 1rem rgba(7, 33, 144, 0.12) !important;
}

/* Print */
@media print {
  #sidebar, .navbar, .btn, .alert { display: none !important; }
  #page-content { margin: 0 !important; }
}

/* Gráfico de Composición % (finanzas/analisis.html) -- alto responsivo en vez
   de un height fijo en el <canvas>, para que las 3 vistas (horizontal,
   evolución apilada, divergente) tengan espacio suficiente sin recortarse. */
.fin-composicion-chart {
  position: relative;
  min-height: 360px;
}
@media (max-width: 576px) {
  .fin-composicion-chart {
    min-height: 420px;
  }
}
