/* Botones */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.7rem 1.4rem;
    border-radius: var(--border-radius);
    font-weight: 600;
    font-size: 0.875rem;
    transition: all var(--transition-fast);
    gap: 0.5rem;
}

.btn-primary {
    background-color: var(--accent-primary);
    /* --on-accent: texto con contraste AA sobre el acento en ambos modos. */
    color: var(--on-accent);
    font-weight: 700;
}

.btn-primary:hover {
    background-color: var(--accent-primary-hover);
}

.btn-secondary {
    background-color: var(--bg-secondary);
    color: var(--text-secondary);
    border: 1px solid var(--border-color);
}

.btn-secondary:hover {
    border-color: var(--accent-primary);
    color: var(--accent-primary);
}

/* Acción destructiva discreta: tinte de su propio color con la tinta medida
   (--error-ink) y, al pasar por encima, el rojo sólido con su tinta de token
   (--on-error). Ni el tinte ni la tinta pueden ser literales: en oscuro el rojo
   se aclara y un blanco fijo encima cae bajo el mínimo AA. */
.btn-danger {
    background-color: color-mix(in srgb, var(--error) 12%, var(--bg-secondary));
    color: var(--error-ink);
    border: 1px solid color-mix(in srgb, var(--error) 35%, var(--bg-secondary));
}

.btn-danger:hover {
    background-color: var(--error);
    color: var(--on-error);
    border-color: var(--error);
}

/* Botón mini: acción secundaria dentro de un panel o una fila de tabla.
   Vocabulario compartido por Motor SECOP, Panel y Licitaciones; las páginas
   pueden afinarlo, pero la forma base (alto, radio y hover) vive aquí. */
.btn-mini {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font: inherit;
    font-size: 12.5px;
    font-weight: 600;
    padding: 6px 12px;
    border-radius: var(--border-radius-sm);
    border: 1px solid var(--border-color);
    background: var(--bg-secondary);
    color: var(--text-secondary);
    cursor: pointer;
    white-space: nowrap;
    text-decoration: none;
    transition: color var(--transition-fast), border-color var(--transition-fast);
}

.btn-mini:hover {
    border-color: var(--accent-primary);
    color: var(--accent-primary);
}

.btn-icon-only {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Target táctil cómodo (antes 34px). */
    width: 36px;
    height: 36px;
    padding: 0 !important;
    border-radius: var(--border-radius-sm);
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    transition: border-color var(--transition-fast), color var(--transition-fast);
    flex-shrink: 0;
    color: var(--text-secondary);
}

.btn-icon-only:hover {
    border-color: var(--accent-primary);
    color: var(--accent-primary);
}

.btn-icon-only svg {
    width: 18px;
    height: 18px;
}

/* Inputs y Formularios */
.form-group {
    margin-bottom: 1.5rem;
}

.form-label {
    display: block;
    margin-bottom: 0.6rem;
    font-size: 0.95rem;
    color: var(--text-secondary);
    font-weight: 500;
}

.form-input {
    width: 100%;
    padding: 0.8rem 1rem;
    background-color: var(--bg-secondary);
    /* Trazo de CONTROL, no Trazo de Plano: el campo tiene el MISMO fondo que la
       tarjeta que lo contiene, así que este borde es lo único que lo identifica
       y debe cumplir 3:1 (SC 1.4.11). Con --border-color medía 1.20-1.96:1. */
    border: 1px solid var(--control-border);
    border-radius: var(--border-radius-sm);
    color: var(--text-primary);
    font-family: inherit;
    font-size: 0.95rem;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form-input:focus {
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 2px rgba(var(--accent-primary-rgb), 0.2);
}

.form-input::placeholder {
    color: var(--text-muted);
}

/* Las clases de campo locales de cada página viven en un <style> inyectado en
   tiempo de ejecución, así que van DESPUÉS de esta hoja y ganarían por orden a
   igualdad de especificidad. Cualificar por elemento (0,1,1 frente a 0,1,0) las
   alcanza sin tener que editar cada página, y sigue perdiendo contra los
   :focus/:focus-visible de esas mismas páginas, que son (0,2,0). */
input.cf-input, select.cf-input, textarea.cf-input,
input.pb-input, select.pb-select, textarea.pb-textarea,
input.pb-inline-input, select.pb-inline-select,
input.search-input-pro, select.filter-select,
input.input-secret, input.pct-input, input.pf-pct-input {
    border-color: var(--control-border);
}

/* ── Campos de secreto (API keys, tokens) ────────────────────────────────────
   NO deben ser input[type=password]. El gestor de contraseñas del navegador
   vigila todo campo de contraseña con valor y, cuando el router SPA lo saca
   del DOM al cambiar de módulo, lo interpreta como un envío de login y ofrece
   "¿Quieres actualizar la contraseña?" con la API key dentro. Se enmascaran
   por CSS sobre un input de texto, que el gestor ignora.
   El JS (components/secret-input.js) hace fallback a type=password si el motor
   no soporta -webkit-text-security. */
.input-secret {
    -webkit-text-security: disc;
    text-security: disc;
    letter-spacing: 0.06em;
}

.input-secret.is-revealed {
    -webkit-text-security: none;
    text-security: none;
    letter-spacing: normal;
}

/* Sidebar */
.sidebar {
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
    width: var(--sidebar-width);
    background-color: var(--bg-secondary);
    border-right: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    z-index: 100;
    transition: transform var(--transition-normal);
}

.sidebar-logo {
    /* El layout es controlado por inline styles en sidebar.js (fila compacta) */
    border-bottom: 1px solid var(--border-color);
    color: var(--text-primary);
    overflow: hidden;
}

.sidebar-nav {
    padding: 0.6rem 0.85rem 1rem 0.85rem;
    flex: 1;
    overflow-y: auto;
    /* Scrollbar fina y sutil: si el contenido supera el alto del viewport,
       la barra no debe ser la gruesa gris por defecto (roba ancho y afea). */
    scrollbar-width: thin;
    scrollbar-color: var(--border-color) transparent;
}
.sidebar-nav::-webkit-scrollbar { width: 6px; }
.sidebar-nav::-webkit-scrollbar-track { background: transparent; }
.sidebar-nav::-webkit-scrollbar-thumb {
    background: var(--border-color);
    border-radius: 999px;
}
.sidebar-nav::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

.nav-item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.62rem 0.7rem;
    color: var(--text-secondary);
    border-radius: var(--border-radius-sm);
    margin-bottom: 0.28rem;
    transition: all var(--transition-fast);
    font-size: 0.92rem;
    /* Una sola línea: densidad y ancho ajustados para que el label más largo
       ("Motor SECOP II" + badge) quepa COMPLETO sin truncar ni hacer wrap.
       El ellipsis queda solo como red de seguridad para textos extremos. */
    white-space: nowrap;
    min-width: 0;
}

/* El texto del ítem (nodo suelto) no se puede truncar directamente; en sidebar.js
   va envuelto en .nav-item-label, que sí toma el espacio flexible y trunca. */
.nav-item .nav-item-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nav-item:hover, .nav-item.active {
    background-color: rgba(var(--accent-primary-rgb), 0.1);
    color: var(--accent-primary);
}

.nav-item svg {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

/* ── Drawer móvil ─────────────────────────────────────────────────────────
   Bajo 768px la sidebar se oculta (transform) y se abre como drawer desde el
   botón hamburguesa del header, con overlay y cierre por Escape/clic fuera. */
.menu-toggle { display: none; }

.sidebar-overlay {
    position: fixed;
    inset: 0;
    background: var(--modal-backdrop);
    z-index: var(--z-overlay);
}

@media (max-width: 768px) {
    .menu-toggle { display: inline-flex; }
    .sidebar {
        transform: translateX(-100%);
        z-index: calc(var(--z-overlay) + 1); /* por encima del overlay */
    }
    .sidebar.open {
        transform: translateX(0);
        box-shadow: var(--shadow-overlay); /* elevación real: drawer = overlay */
    }
}

/* Header */
.top-header {
    height: var(--header-height);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 2rem;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border-color);
    position: sticky;
    top: 0;
    z-index: 90;
}

.header-title {
    font-size: 20px;   /* Headline (DESIGN.md) */
    font-weight: 600;
}

/* ── Selector de tema (popover del header) ───────────────────────────────────
   Superficie plana con borde y la sombra ÚNICA del sistema (--shadow-overlay),
   que es un overlay real. Sin blur ni gradiente (Flat-By-Default Rule).
   El marcado y el teclado los pone header.js: role="menu" con
   role="menuitemradio" por opción. */
.theme-menu-wrap {
    position: relative;
    display: flex;
    align-items: center;
}

.theme-menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 268px;
    max-height: min(72vh, 560px);
    overflow-y: auto;
    padding: var(--space-1);
    background: var(--bg-secondary);
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius);
    box-shadow: var(--shadow-overlay);
    z-index: var(--z-overlay);
    display: none;
    flex-direction: column;
    gap: 2px;
}

.theme-menu[data-open="true"] {
    display: flex;
}

/* Contenedor de grupo (role="group" rotulado por su título). Replica el flujo
   del menú para que envolver los ítems no altere ni el orden ni el ritmo. */
.theme-menu-groupbox {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.theme-menu-group {
    padding: var(--space-2) var(--space-2) var(--space-1);
    font-size: 11px;            /* The 11px Floor Rule */
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.theme-menu-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    padding: var(--space-2);
    border: 1px solid transparent;
    border-radius: var(--border-radius-sm);
    background: transparent;
    color: var(--text-primary);
    text-align: left;
    font-size: 14px;
    transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.theme-menu-item:hover {
    background: var(--bg-tertiary);
}

.theme-menu-item[aria-checked="true"] {
    background: rgba(var(--accent-primary-rgb), 0.10);
    border-color: rgba(var(--accent-primary-rgb), 0.35);
}

/* Muestra del material: el fondo de página del tema, con su superficie de
   trabajo y su acento dentro — los tres colores que de verdad se ven. Los
   valores los inyecta header.js leyéndolos de index.css, sin duplicarlos. */
.theme-swatch {
    flex: none;
    width: 36px;
    height: 24px;
    border-radius: 4px;
    border: 1px solid var(--glass-border);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
}

.theme-swatch i {
    display: block;
    width: 11px;
    height: 13px;
    border-radius: 2px;
}

.theme-menu-text {
    flex: 1;
    min-width: 0;
}

.theme-menu-label {
    font-weight: 500;
    line-height: 1.3;
}

.theme-menu-item[aria-checked="true"] .theme-menu-label {
    font-weight: 700;
}

.theme-menu-hint {
    display: block;
    font-size: 12px;
    color: var(--text-muted);
    line-height: 1.35;
    margin-top: 2px;
}

.theme-menu-check {
    flex: none;
    width: 16px;
    height: 16px;
    color: var(--accent-primary);
}

/* Tarjetas (Cards) */
.card {
    background: var(--bg-secondary);
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius);
    padding: 1.5rem;
}

.card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 1.5rem;
}

/* File Upload Component */
.file-upload-zone {
    border: 2px dashed var(--border-color);
    border-radius: var(--border-radius);
    padding: 3rem 2rem;
    text-align: center;
    cursor: pointer;
    transition: all var(--transition-fast);
    background-color: var(--bg-secondary);
}

.file-upload-zone:hover, .file-upload-zone.dragover {
    border-color: var(--accent-primary);
    background-color: rgba(var(--accent-primary-rgb), 0.05);
}

.file-upload-zone svg {
    width: 48px;
    height: 48px;
    color: var(--accent-primary);
    margin-bottom: 1rem;
}

.file-list {
    margin-top: 1.5rem;
}

.file-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem;
    background: var(--bg-tertiary);
    border-radius: var(--border-radius-sm);
    margin-bottom: 0.5rem;
}

/* Toast Notificaciones */
.toast-container {
    position: fixed;
    /* Arriba-centro: visible aunque haya DevTools abierto o paneles laterales.
       Antes estaba en bottom/right y quedaba tapado por el panel del Asistente. */
    top: 1.25rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    /* stretch (no center): todos los toasts comparten ancho y sus bordes quedan
       alineados al apilarse. Antes con center cada toast tenía su propio ancho y
       el apilado se veía escalonado. */
    align-items: stretch;
    gap: 0.75rem;
    pointer-events: none; /* el contenedor no bloquea clics; cada toast los reactiva */
}

.toast {
    padding: 1rem 1.5rem;
    background: var(--bg-secondary);
    /* Estado comunicado por borde 1px + icono coloreado + texto (nunca solo color).
       Sombra permitida: el toast es un overlay real. */
    border: 1px solid var(--success);
    border-radius: var(--border-radius);
    box-shadow: var(--shadow-overlay);
    color: var(--text-primary);
    display: flex;
    align-items: center;
    gap: 0.8rem;
    /* Ancho uniforme para que el apilado quede alineado y legible. */
    min-width: 300px;
    max-width: 440px;
    pointer-events: auto; /* reactiva clics (el contenedor es pointer-events:none) */
    animation: slideDownTop 0.3s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

/* El ícono toma el color del tipo (antes quedaba blanco: currentColor = texto).
   Así un toast de error tiene ✕ roja, uno de éxito ✓ verde, etc. */
.toast > svg { flex-shrink: 0; color: var(--success); }
.toast.error > svg { color: var(--error); }
.toast.info > svg { color: var(--info); }
.toast.warning > svg { color: var(--warning); }

.toast.error { border-color: var(--error); }
.toast.info { border-color: var(--info); }
.toast.warning { border-color: var(--warning); }

/* Entrada del toast (arriba-centro): baja desde el borde superior con un leve
   rebote. El cierre (main.js) la reproduce en reverse → sube y se desvanece. */
@keyframes slideDownTop {
    from { opacity: 0; transform: translateY(-120%); }
    to   { opacity: 1; transform: translateY(0); }
}
/* Conservada por compatibilidad: main.js antiguo podía referenciarla. */
@keyframes slideInRight {
    from { opacity: 0; transform: translateX(120%); }
    to   { opacity: 1; transform: translateX(0); }
}

/* Toasts y Notificaciones - Fin */

/* Progress Bars */
.progress-container {
    width: 100%;
    height: 8px;
    background: var(--bg-tertiary);
    border-radius: 999px;
    overflow: hidden;
    margin: 1.5rem 0;
    border: 1px solid var(--border-color);
}

/* El relleno ocupa siempre el 100% y se escala: animar 'width' obliga al
   navegador a recalcular layout en cada fotograma; 'transform' se compone en
   la GPU. El progreso se fija con --progress (0-1) o con style.width, que el
   JS traduce; el origen a la izquierda hace que crezca desde el inicio.
   (Comillas simples a propósito: el proyecto prohíbe el acento grave en
   comentarios CSS, porque esta hoja puede acabar dentro de un template
   literal y cerraría la cadena.) */
.progress-bar {
    height: 100%;
    width: 100%;
    transform: scaleX(var(--progress, 0));
    transform-origin: left center;
    background: var(--accent-primary);
    transition: transform 0.3s ease;
}

@media (prefers-reduced-motion: reduce) {
    .progress-bar { transition: none; }
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

.spinner-small {
    border: 2px solid var(--border-color);
    border-top-color: var(--accent-primary);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

/* Estilos para Contenido Renderizado por IA (Rich Reports) */
.ai-render-content {
    font-family: inherit;
    font-size: 1rem;
    line-height: 1.8;
    color: var(--text-secondary);
}

.ai-render-content h1, .ai-render-content h2, .ai-render-content h3 {
    color: var(--text-primary);
    margin-top: 1.5rem;
    margin-bottom: 1rem;
    font-weight: 700;
}

.ai-render-content h3 {
    font-size: 1.1rem;
}

.ai-render-content p {
    margin-bottom: 1.2rem;
}

.ai-render-content ul, .ai-render-content ol {
    margin-bottom: 1.5rem;
    padding-left: 1.5rem;
}

.ai-render-content li {
    margin-bottom: 0.5rem;
}

.ai-render-content table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin: 1.5rem 0;
    background: var(--bg-secondary);
    border-radius: var(--border-radius);
    overflow: hidden;
    border: 1px solid var(--border-color);
}

.ai-render-content th {
    background: var(--bg-tertiary);
    color: var(--text-secondary);
    text-align: left;
    padding: 1rem;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border-bottom: 1px solid var(--border-color);
}

.ai-render-content td {
    padding: 1rem;
    font-size: 0.9rem;
    border-bottom: 1px solid var(--border-color);
}

.ai-render-content tr:last-child td {
    border-bottom: none;
}

.ai-render-content tr:hover {
    background: var(--bg-tertiary);
}

.ai-render-content strong {
    color: var(--text-primary);
    font-weight: 600;
}

.ai-render-content blockquote {
    border: 1px solid var(--border-color);
    background: rgba(var(--accent-primary-rgb), 0.05);
    padding: 1rem 1.5rem;
    margin: 1.5rem 0;
    border-radius: var(--border-radius);
    font-style: italic;
}

/* ============================================================================
   Cursor-tooltip — tooltip que sigue el cursor para textos truncados.
   Antes vivia dentro del <style> inline del dashboard, pero el div se inyecta
   a document.body y sobrevive a los cambios de pagina (router.innerHTML).
   Si el CSS no es global, al navegar fuera del dashboard el div queda huerfano
   sin estilos y se ve como un parrafo de texto pegado al final del body.
   ============================================================================ */
#cursor-tooltip {
    position: fixed;
    z-index: 10000;
    pointer-events: none;
    max-width: 720px;
    padding: 0.75rem 1.1rem;
    background: var(--text-primary);
    color: var(--bg-primary);
    border-radius: var(--border-radius-sm);
    box-shadow: var(--shadow-overlay);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 500;
    line-height: 1.5;
    letter-spacing: 0.01em;
    text-align: center;
    white-space: normal;
    word-break: break-word;
    opacity: 0;
    transform: translateY(4px);
    transition: opacity 0.12s ease, transform 0.12s ease;
}
#cursor-tooltip.show {
    opacity: 1;
    transform: translateY(0);
}
