/* ====================================================================
   VARIABLES GLOBALES
   ==================================================================== */

:root {
    --bg-color: #f4f6f9;
    --card-bg: #ffffff;
    --text-main: #333333;
    --text-secondary: #666666;
    --text-muted: #898781;
    --accent-blue: #375a7f;
    --accent-blue-dark: #023564;
    --accent-light: #e9ecef;
    --border-color: #e1e0d9;
    --border-radius: 12px;
    --shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
    --shadow-hover: 0 6px 18px rgba(0, 0, 0, 0.08);
    --color-error: #BB4A4A;
    --color-exito: #168980;
    --color-advertencia: #c98500;
}

/* ====================================================================
   BASE
   ==================================================================== */

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

body {
    background-color: var(--bg-color);
    color: var(--text-main);
    padding: 20px;
}

/* Mensajes de éxito / error reutilizados en toda la app
   (formularios, catálogos, usuarios, edición) */
.mensaje-error {
    color: var(--color-error);
    font-weight: 600;
    margin-top: 8px;
}

.mensaje-exito {
    color: var(--color-exito);
    font-weight: 600;
    margin-top: 8px;
}

.mensaje-info {
    color: var(--text-secondary);
    font-weight: 600;
    margin-top: 8px;
}

/* Aviso de "no tiene permisos" al entrar a un módulo restringido */
.alerta-permiso {
    color: var(--color-error);
    font-weight: 600;
    padding: 20px;
}


/* ====================================================================
   LAYOUT / GRID
   ==================================================================== */

.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: 20px;
}

.col-3 { grid-column: span 3; }
.col-4 { grid-column: span 4; }
.col-6 { grid-column: span 6; }
.col-8 { grid-column: span 8; }
.col-12 { grid-column: span 12; }

.dashboard-page {
    padding: 20px;
}

.dashboard-subtitle {
    color: var(--text-secondary);
    margin-top: 4px;
    margin-bottom: 15px;
}

/* Introducción breve al inicio de cada pestaña de Visualización
   (Comunidad, Medios, Histórico), antes de los filtros: una idea
   principal en negrita (<strong>) y qué preguntas responde la página.
   La barra lateral la ancla visualmente sin convertirla en otra
   tarjeta que compita con la de filtros. */
.pagina-intro {
    color: var(--text-secondary);
    font-size: 0.95rem;
    line-height: 1.5;
    max-width: 90ch;
    margin: 20px 0 18px;
    padding: 2px 0 2px 12px;
    border-left: 3px solid var(--accent-blue-dark);
}

.pagina-intro strong {
    color: var(--text-main);
    font-weight: 600;
}

.section-label {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin: 22px 0 10px;
}

.section-label:first-child {
    margin-top: 0;
}

.filtros-card {
    background: var(--card-bg);
    border-radius: var(--border-radius);
    box-shadow: var(--shadow);
    padding: 16px 20px;
    margin-bottom: 20px;
}

.filtros-label {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 8px;
}

.charts-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
}

.filtros-grid {
    display: grid;
    grid-template-columns: 1.3fr 1fr 1fr 1fr;
    gap: 10px;
    margin-bottom: 12px;
}

/* El selector de fecha (dcc.DatePickerSingle/Range) no trae una
   altura fija como los Dropdown/Input, así que sobresalía más alto
   cuando comparte fila con ellos (ej. filtros de Edición). */
.dash-datepicker-input-wrapper {
    height: 34px;
    box-sizing: border-box;
}

@media (max-width: 992px) {
    .col-3 { grid-column: span 6; }
    .col-4 { grid-column: span 6; }
    .col-8 { grid-column: span 12; }
}

@media (max-width: 768px) {
    .charts-grid {
        grid-template-columns: 1fr;
    }

    .filtros-grid {
        display: flex;
        flex-direction: column;
    }
}

@media (max-width: 600px) {
    .col-3, .col-4, .col-6, .col-8, .col-12 {
        grid-column: span 12;
    }

    body {
        padding: 10px;
    }
}


/* ====================================================================
   TARJETAS (CARD BASE Y KPI)
   ==================================================================== */

.card {
    background: var(--card-bg);
    border-radius: var(--border-radius);
    padding: 20px;
    box-shadow: var(--shadow);
    display: flex;
    flex-direction: column;
    transition: box-shadow .2s ease;
}

.card:hover {
    box-shadow: var(--shadow-hover);
}

.card h3 {
    font-size: 1rem;
    color: var(--text-main);
    margin-bottom: 10px;
    font-weight: 600;
}

.kpi-card {
    text-align: center;
    justify-content: center;
    border-top: 4px solid var(--accent-blue-dark);
}

.kpi-card-positivo {
    border-top-color: var(--color-exito);
}

.kpi-card-negativo {
    border-top-color: var(--color-error);
}

.kpi-card-neutral {
    border-top-color: var(--text-secondary);
}

.kpi-value {
    font-size: 2rem;
    font-weight: bold;
    color: var(--accent-blue-dark);
}

.kpi-card-positivo .kpi-value {
    color: var(--color-exito);
}

.kpi-card-negativo .kpi-value {
    color: var(--color-error);
}

.kpi-card-neutral .kpi-value {
    color: var(--text-secondary);
}

.kpi-label {
    font-size: 0.9rem;
    color: var(--text-secondary);
    margin-top: 5px;
}

.kpi-subtitle {
    font-size: 0.8rem;
    color: var(--text-secondary);
    margin-top: 3px;
}

.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 340px));
    gap: 15px;
    margin-bottom: 20px;
}


/* ====================================================================
   HISTÓRICO (comparación mes vs mes anterior)
   ==================================================================== */

.historico-section-header {
    text-align: center;
    margin: 36px 0 18px;
    padding-bottom: 14px;
    border-bottom: 3px solid var(--accent-blue-dark);
}

.historico-section-header:first-child {
    margin-top: 0;
}

.historico-section-title {
    font-size: 2.2rem;
    font-weight: 800;
    color: var(--accent-blue-dark);
    margin: 1em 0 0;
    line-height: 1.2;
}

.historico-section-subtitle {
    font-size: 0.95rem;
    color: var(--text-secondary);
    margin: 4px 0 0;
}

.tendencia-selectores {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
    margin-bottom: 12px;
}

.tendencia-selector {
    display: flex;
    align-items: center;
    gap: 10px;
}

.tendencia-selector-label {
    font-size: 0.85rem;
    color: var(--text-secondary);
    white-space: nowrap;
}

.tendencia-selector-dropdown {
    min-width: 220px;
}

.comparison-footer {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    margin-top: 10px;
}

.comparison-anterior {
    font-size: 0.78rem;
    color: var(--text-secondary);
}

.comparison-delta {
    font-size: 0.85rem;
    font-weight: 700;
    white-space: nowrap;
}

/* Total, Alcance, Participación, Compromiso: subir o bajar no es en
   sí mismo bueno ni malo, así que ambas direcciones usan el mismo
   azul en vez de verde/rojo. */
.comparison-delta-neutro {
    color: #1a6fd1;
}

.comparison-delta-neutral {
    color: var(--text-secondary);
}

/* Índice Reputacional: único indicador de Histórico donde "bajar" es
   inequívocamente malo (se acerca a -1), así que es el único que usa
   rojo/verde en vez del azul neutral de los demás. */
.comparison-delta-indice-mejora {
    color: var(--color-exito);
}

.comparison-delta-indice-empeora {
    color: var(--color-error);
}

.aviso-mes-en-curso {
    display: flex;
    align-items: center;
    gap: 10px;
    background: #fff3cd;
    border: 2px solid var(--color-advertencia);
    border-left: 6px solid var(--color-advertencia);
    border-radius: var(--border-radius);
    padding: 14px 18px;
    margin-bottom: 20px;
    color: #7a5400;
    font-size: 0.95rem;
    font-weight: 600;
    box-shadow: var(--shadow);
}

.aviso-sin-comparacion {
    color: var(--text-secondary);
    font-size: 0.85rem;
    margin-bottom: 20px;
}


/* ====================================================================
   GRÁFICOS (contenedores de dcc.Graph)
   ==================================================================== */

/* Se combina con la clase "card" (fondo, sombra, borde redondeado,
   título h3); esta clase solo agrega el comportamiento de scroll
   propio de un contenedor de gráfico. */
.chart-container {
    overflow: auto;
    max-width: 100%;
    max-height: 100%;
}

.chart-container-scroll {
    max-height: 480px;
    overflow-y: auto;
    overflow-x: hidden;
}

/* Leyenda propia (círculos de color) para donut_chart.py, en vez de
   la leyenda nativa de Plotly, estilo Chart.js. */
.chart-legend {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 16px;
    margin-top: 4px;
}

.chart-legend-item {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.85rem;
    color: var(--text-secondary);
}

.chart-legend-swatch {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}

.chart-empty-state {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 200px;
    color: var(--text-secondary);
    font-size: 0.95rem;
    text-align: center;
}

.gauge-caption {
    text-align: center;
    color: var(--text-main);
    margin-top: -10px;
}


/* ====================================================================
   GAUGE (medidor CSS puro, no usado por gauge_chart.py actual con
   Plotly, se deja disponible por si se vuelve a un gauge en CSS)
   ==================================================================== */

.gauge-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    position: relative;
}

.gauge {
    width: 160px;
    height: 80px;
    position: relative;
    overflow: hidden;
}

.gauge-body {
    width: 160px;
    height: 160px;
    border-radius: 50%;
    background: var(--accent-light);
    position: absolute;
    top: 0;
    left: 0;
}

.gauge-fill {
    width: 100%;
    height: 100%;
    background: var(--accent-blue);
    position: absolute;
    top: 0;
    left: 0;
    border-radius: 50%;
    clip-path: polygon(0 0, 100% 0, 100% 50%, 0 50%);
    transform: rotate(0.55turn);
    transform-origin: center center;
}

.gauge-cover {
    width: 110px;
    height: 110px;
    background: var(--card-bg);
    border-radius: 50%;
    position: absolute;
    top: 25px;
    left: 25px;
}

.gauge-value {
    font-size: 1.8rem;
    font-weight: bold;
    color: var(--accent-blue);
    margin-top: -30px;
    z-index: 2;
}


/* ====================================================================
   BARRAS DE PROGRESO
   ==================================================================== */

.progress-bar-container {
    margin-bottom: 12px;
}

.progress-info {
    display: flex;
    justify-content: space-between;
    font-size: 0.85rem;
    margin-bottom: 4px;
}

.progress-bg {
    background-color: var(--accent-light);
    height: 8px;
    border-radius: 4px;
    overflow: hidden;
}

.progress-fill {
    background-color: var(--accent-blue);
    height: 100%;
    border-radius: 4px;
}


/* ====================================================================
   TABLAS
   ==================================================================== */

.table-container {
    width: 100%;
    overflow-x: auto;
}

table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 10px;
}

th, td {
    padding: 10px 12px;
    text-align: left;
    border-bottom: 1px solid var(--accent-light);
    font-size: 0.9rem;
}

th {
    background-color: #f8f9fa;
    color: var(--text-secondary);
    font-weight: 600;
}

tr:hover {
    background-color: #f8f9fa;
}


/* ====================================================================
   TABLA DE EDICIÓN (dropdowns editables)
   ==================================================================== */
/* El contenedor de dash_table necesita scroll horizontal
   (overflow-x: auto) porque la tabla tiene muchas columnas; por
   comportamiento propio de CSS, eso obliga al navegador a recortar
   también el overflow vertical. El menú desplegable de las columnas
   editables (red social, tema, sentimiento...) se posiciona debajo
   de la celda, así que en las últimas filas visibles ese recorte le
   corta el menú. Mientras haya un menú abierto en algún lado de la
   tabla, se le da aire abajo al contenedor para que el menú no
   choque contra ese borde. */
#tabla-edicion .dash-spreadsheet-container:has(.Select-menu-outer) {
    padding-bottom: 230px;
}

.app-header {
    display: flex;
    justify-content: space-between;
    align-items: center;

    padding: 15px 25px;

    background-color: #023564;
    color: #ffffff;

    border-radius: var(--border-radius);
    margin-bottom: 20px;
    box-shadow: var(--shadow);
}

.header-brand {
    display: flex;
    align-items: center;
    gap: 15px;
}

.app-logo {
    height: 40px;
}

.app-title {
    margin: 0;
    color: white;
    font-size: 1.4rem;
}

.header-user {
    display: flex;
    align-items: center;
    gap: 15px;
}

.user-info {
    display: flex;
    flex-direction: column;
    text-align: right;
}

.user-name {
    font-weight: 600;
}

.user-role {
    font-size: 0.85rem;
    opacity: 0.8;
}

.logout-button {
    background: white;
    color: #023564;
    border: none;
    border-radius: 6px;
    padding: 8px 12px;
    cursor: pointer;
    font-weight: 600;
}

.menu-button {
    display: none;

    background: transparent;
    color: white;
    border: none;

    font-size: 24px;
    cursor: pointer;
}

.header-nav {
    display: flex;
    gap: 10px;
    align-items: center;
}

.nav-button {
    background: transparent;
    color: white;
    border: 1px solid rgba(255,255,255,.3);

    padding: 8px 14px;

    border-radius: 6px;
    cursor: pointer;
    margin-left: 12px;

    transition: all .2s ease;
}

.nav-button:hover {
    background: rgba(255,255,255,.15);
}

.nav-button.active {
    background: white;
    color: #023564;
    font-weight: 600;
}

@media (max-width: 768px) {

    .menu-button {
        display: block;
    }

    .app-title {
        font-size: 1.1rem;
    }

    .user-role {
        display: none;
    }

    .app-header {
        flex-direction: column;
        align-items: stretch;
    }

    .header-nav {
        display: none;
        flex-direction: column;
        width: 100%;
        margin-top: 10px;
    }

    .header-nav.open {
        display: flex;
    }

    .header-nav button {
        width: 100%;
    }
}


/* ====================================================================
   LOGIN
   ==================================================================== */

.login-page {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 25px;
    min-height: calc(100vh - 40px);
}

.login-box {
    width: 100%;
    max-width: 340px;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    text-align: center;
    padding: 35px 30px;
}

.login-logo {
    max-width: 220px;
    width: 100%;
    height: auto;
}

.login-box h2 {
    margin-bottom: 20px;
    color: var(--text-main);
}

/* dcc.Input en esta versión de Dash ya es un componente nativo
   (.dash-input-container envolviendo el <input> real): trae su
   propia caja de 34px de alto con su propio padding interno. Ponerle
   ACÁ padding/border/border-radius propios (como antes) se suma al
   padding que ya trae por dentro, y entre los dos aplastan el texto
   a unos pocos px de alto dentro de esos 34px fijos — el bug de "no
   se ven las letras completas". Solo hace falta el espaciado entre
   campos; el resto del estilo visual ya lo pone Dash. */
.login-input {
    margin-bottom: 12px;
}

.login-button {
    width: 100%;
    margin-top: 5px;
}

.login-message {
    margin-top: 15px;
}

.login-message .mensaje-error {
    margin-top: 0;
}

/* Pantalla de primer ingreso (components/primer_ingreso.py): reutiliza
   la caja del login, un poco más ancha y con los campos alineados a la
   izquierda con su etiqueta encima. */
.primer-ingreso-box {
    max-width: 420px;
}

.primer-ingreso-texto {
    color: var(--text-secondary);
    font-size: 0.92rem;
    line-height: 1.5;
    margin: -8px 0 20px;
}

.primer-ingreso-campos {
    display: flex;
    flex-direction: column;
    text-align: left;
}

.primer-ingreso-campos label {
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin-bottom: 4px;
}

.primer-ingreso-salir {
    margin-top: 18px;
    background: none;
    border: none;
    color: var(--text-secondary);
    font-size: 0.85rem;
    text-decoration: underline;
    cursor: pointer;
}

.primer-ingreso-salir:hover {
    color: var(--text-main);
}


/* ====================================================================
   FORMULARIOS (Registro de Comunidad / Medios, Configuración)
   ==================================================================== */

.formulario-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 15px;
    margin-bottom: 20px;
}

.campo-formulario {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.campo-formulario label {
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--text-secondary);
}

.campo-formulario input,
.campo-formulario textarea {
    width: 100%;
    padding: 8px;
    border: 1px solid var(--accent-light);
    border-radius: 6px;
    font-size: 0.9rem;
}

/* La regla de arriba también alcanzaba a los <input> internos del
   selector de fecha (dcc.DatePickerSingle/Range), que ya van dentro
   del recuadro de .dash-datepicker-input-wrapper: con su propio borde
   y padding quedaban como cajas de 50px de alto que se salían de ese
   recuadro. */
.campo-formulario .dash-datepicker-input {
    width: auto;
    padding: 0;
    border: none;
    border-radius: 0;
    background: transparent;
}

/* Filtro de fecha de Edición (rango): mientras no se eligió ninguna
   fecha, el recuadro dice solo "Elegir fecha" — sin la flecha ni el
   segundo "Elegir fecha" del campo de fecha final. En cuanto se elige
   una fecha (el campo deja de mostrar el placeholder), vuelven a
   aparecer los dos campos del rango. */
#edicion-fecha-wrapper:has(#edicion-fecha:placeholder-shown):has(#edicion-fecha-end-date:placeholder-shown) .dash-datepicker-range-arrow,
#edicion-fecha-wrapper:has(#edicion-fecha:placeholder-shown):has(#edicion-fecha-end-date:placeholder-shown) #edicion-fecha-end-date {
    display: none;
}

.campo-formulario-ancho {
    grid-column: span 3;
}

/* Fila de likes/comentarios/compartidos/seguidores en Registro de
   Medios: solo se muestra cuando "¿Alcance medible?" es Sí (ver
   callback mostrar_metricas_medios en auth_callbacks.py, que
   alterna el "display" por estilo en línea). */
.campo-formulario-metricas {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 15px;
}

@media (max-width: 768px) {
    .formulario-grid {
        grid-template-columns: 1fr;
    }

    .campo-formulario-ancho {
        grid-column: span 1;
    }

    .campo-formulario-metricas {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Fila de botones de acción del catálogo (Agregar / Actualizar / Eliminar) */
.acciones-catalogo {
    display: flex;
    gap: 10px;
    align-items: center;
    margin-top: 10px;
    flex-wrap: wrap;
}

.input-editar-catalogo {
    width: 350px;
    max-width: 100%;
}

/* ====================================================================
   ADMINISTRACIÓN DE USUARIOS
   ==================================================================== */

.input-buscar-usuario {
    width: 350px;
    max-width: 100%;
    margin: 10px 0;
    padding: 8px;
    border: 1px solid var(--accent-light);
    border-radius: 6px;
    font-size: 0.9rem;
}

.instruccion-tabla-usuarios {
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin: 0 0 10px;
}


/* ====================================================================
   PÁGINA DE BIENVENIDA (home)
   ==================================================================== */

.home-page {
    padding: 20px;
}

.texto-ultimo-login {
    color: var(--text-secondary);
    margin-top: 5px;
}

.texto-instruccion-home {
    margin-top: 15px;
    margin-bottom: 15px;
}

.accesos-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 220px));
    gap: 15px;
}

.acceso-directo-button {
    background: var(--card-bg);
    color: var(--accent-blue);

    border: 1px solid var(--accent-light);
    border-radius: var(--border-radius);
    box-shadow: var(--shadow);

    padding: 25px 15px;

    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;

    transition: all .2s ease;
}

.acceso-directo-button:hover {
    background: var(--accent-blue);
    color: white;
}


/* ====================================================================
   EXPORTAR (Excel / PDF en los dashboards)
   ==================================================================== */

.export-bar {
    display: flex;
    gap: 10px;
    margin-bottom: 20px;
}

.btn-export {
    border: none;
    border-radius: 6px;
    padding: 8px 16px;
    font-weight: 600;
    cursor: pointer;
    color: white;
    margin-top: 16px;
}

.btn-export-excel {
    background-color: #1e7145;
}

.btn-export-excel:hover {
    background-color: #24904f;
}

.btn-export-pdf {
    background-color: #a3312c;
}

.btn-export-pdf:hover {
    background-color: #c13d37;
}

.btn-export-analisis {
    background-color: var(--accent-blue-dark);
}

.btn-export-analisis:hover {
    background-color: var(--accent-blue);
}

/* Botón "Análisis" oculto por ahora (pedido 2026-10-05). Se oculta con
   CSS en vez de quitarlo del layout para no romper los callbacks que
   lo escuchan (auth_callbacks.py); para volver a mostrarlo basta con
   borrar estas dos reglas. La segunda oculta la barra de Histórico,
   donde el botón está solo, para que no quede un espacio vacío. */
.btn-export-analisis,
.export-bar:has(> .btn-export-analisis:only-child) {
    display: none;
}


/* ====================================================================
   MODAL DE ANÁLISIS (resumen de métricas en texto)
   ==================================================================== */

.modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 20px;
}

.modal-card {
    background: var(--card-bg);
    border-radius: var(--border-radius);
    box-shadow: var(--shadow-hover);
    width: 100%;
    max-width: 560px;
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    border-bottom: 1px solid var(--border-color);
    flex-shrink: 0;
}

.modal-header h3 {
    margin: 0;
}

.modal-cerrar {
    background: none;
    border: none;
    font-size: 1.6rem;
    line-height: 1;
    cursor: pointer;
    color: var(--text-secondary);
    padding: 0 4px;
}

.modal-cerrar:hover {
    color: var(--text-main);
}

.modal-body {
    /* flex:1 + min-height:0 es lo que realmente confina el body
       dentro de la altura que le queda al header/footer en el
       flex column de .modal-card — sin min-height:0, un flex item
       nunca se encoge por debajo del alto de su contenido, así que
       un resumen largo empujaba el footer (con el botón de copiar)
       fuera de los 80vh de .modal-card, y como esta tiene
       overflow:hidden, el botón quedaba recortado sin que ningún
       scroll lo hiciera visible. */
    flex: 1 1 auto;
    min-height: 0;
    padding: 20px;
    overflow-y: auto;
    line-height: 1.6;
    color: var(--text-main);
    white-space: pre-line;
}

.modal-body p {
    margin: 0 0 12px 0;
}

.modal-body p:last-child {
    margin-bottom: 0;
}

.modal-footer {
    padding: 12px 20px;
    border-top: 1px solid var(--border-color);
    display: flex;
    justify-content: flex-end;
    flex-shrink: 0;
}

.btn-copiar {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    border-radius: 6px;
    border: 1px solid var(--border-color);
    background: var(--bg-color);
    color: var(--text-main);
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
}

.btn-copiar:hover {
    background: var(--accent-light);
}


/* ====================================================================
   BOTONES
   ==================================================================== */

.btn-save-user {
    background-color: #023564;
    color: white;

    border: none;
    border-radius: 6px;

    padding: 10px 20px;

    cursor: pointer;
    font-weight: 600;
}

.btn-save-user:hover {
    background-color: #03427a;
}

.btn-delete-user {
    background-color: var(--color-error);
    color: white;

    border: none;
    border-radius: 6px;

    padding: 10px 20px;

    cursor: pointer;
    font-weight: 600;
}

.btn-delete-user:hover {
    opacity: 0.9;
}

.btn-activate-user {
    background-color: var(--color-exito);
    color: white;
    border: none;
    border-radius: 6px;
    padding: 10px 20px;
    cursor: pointer;
}

.btn-remove-user {
    background-color: #8B0000;
    color: white;
    border: none;
    border-radius: 6px;
    padding: 10px 20px;
    cursor: pointer;
}

/* ====================================================================
   IMPRESIÓN (Ctrl+P en Visualización, ajustado a A4)
   ==================================================================== */
/* Oculta el encabezado/navegación y los controles interactivos
   (filtros, pestañas, exportar) que no tienen sentido en papel, y
   fuerza los grids de tarjetas/gráficas a una sola columna para que
   nada quede cortado al ancho de la hoja. assets/imprimir.js redibuja
   cada gráfica de Plotly al ancho de su tarjeta en la hoja justo antes
   de imprimir (si no, quedarían con el ancho que tenían en pantalla y
   se recortarían — la dona y el gauge, a la mitad).
   ==================================================================== */

/* Chromium dispara beforeprint todavía con el layout de pantalla, así
   que imprimir.js no podría medir el ancho que va a tener cada tarjeta
   en la hoja. Por eso agrega la clase "imprimiendo" al <html>, y estas
   reglas (fuera de @media print, para que ya apliquen en ese momento)
   reproducen el ancho de la hoja y la grilla de la impresión: A4
   horizontal (29.7cm) menos los márgenes de @page (2 x 1.2cm) = 27.3cm,
   con el padding del body incluido igual que en la hoja. Cualquier
   regla de abajo que cambie anchos (paddings, gaps, bordes, columnas)
   tiene que repetirse acá. */
html.imprimiendo body {
    width: 27.3cm;
}

html.imprimiendo .dashboard-page {
    padding: 0;
}

html.imprimiendo .card {
    border: 1px solid var(--border-color);
}

html.imprimiendo .charts-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
}

html.imprimiendo .charts-grid > * {
    min-width: 0;
}

html.imprimiendo .charts-grid > .chart-container-scroll {
    grid-column: 1 / -1;
}

@media print {

    @page {
        size: A4 landscape;
        margin: 1.2cm;
    }

    body {
        background: #ffffff;
    }

    .app-header,
    #tabs-dashboard,
    #tabs-historico,
    .filtros-card,
    .tendencia-selectores,
    .export-bar,
    .aviso-mes-en-curso,
    .aviso-sin-comparacion {
        display: none !important;
    }

    .dashboard-page {
        padding: 0;
    }

    .card {
        box-shadow: none;
        border: 1px solid var(--border-color);
        break-inside: avoid;
        page-break-inside: avoid;
    }

    .card:hover {
        box-shadow: none;
    }

    /* KPI a 25% de ancho (4 por fila), gráficas a 50% (2 por fila) —
       salvo las "de columna" (bar_chart_h / bar_chart_comparativo,
       identificadas por chart-container-scroll: suelen traer muchas
       categorías y necesitan el ancho completo de la hoja para que
       las etiquetas no queden amontonadas). */
    .kpi-grid {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        gap: 10px;
    }

    .charts-grid {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 10px;
    }

    /* Sin esto, una tarjeta angosta al lado de una gráfica de barras
       ancha (con su SVG en un ancho fijo en px) fuerza a la columna
       de la izquierda a crecer para "caber" ese contenido — porque
       por defecto un ítem de grid no se encoge más allá del tamaño
       de su contenido, y la página completa termina siendo más ancha
       que la hoja. min-width:0 le permite a cada tarjeta encogerse a
       lo que le toca en la grilla en vez de forzarla a crecer.
       (El overflow:hidden del contenido lo maneja chart-container /
       chart-container-scroll aparte). */
    .charts-grid > * {
        min-width: 0;
    }

    .charts-grid > .chart-container-scroll {
        grid-column: 1 / -1;
    }

    .chart-container {
        overflow: visible;
    }

    /* Red de seguridad por si el ancho real en la hoja no coincide
       con el que midió imprimir.js (ej. otro papel u otra escala en
       la vista previa): con el viewBox que le pone imprimir.js,
       width:100% escala el <svg> proporcionalmente al ancho real de
       la tarjeta, y height:auto conserva la proporción. El primer main-svg
       pasa a position:relative para que le dé altura al contenedor
       (Plotly los apila todos en absolute); los demás (capa de hover,
       etc.) quedan encima con el mismo tamaño. */
    html.imprimiendo .chart-container .js-plotly-plot,
    html.imprimiendo .chart-container .plot-container,
    html.imprimiendo .chart-container .svg-container {
        width: 100% !important;
        height: auto !important;
    }

    html.imprimiendo .chart-container .main-svg {
        width: 100% !important;
        height: auto !important;
    }

    html.imprimiendo .chart-container .svg-container > .main-svg:first-of-type {
        position: relative !important;
        display: block;
    }

    /* Las gráficas con muchas categorías (ej. "Noticias por Medio"
       con 30+ medios) crecen mucho más alto que una hoja A4 — sin
       este tope, terminan partidas entre varias páginas, y Chromium
       no dibuja un <svg> partido (la tarjeta sale en blanco). Se
       recortan limpiamente a una hoja: A4 horizontal (21cm) menos los
       márgenes de @page (2 x 1.2cm) = 18.6cm, y un poco menos para
       el título y el padding de la tarjeta. Como vienen ordenadas de
       mayor a menor, lo que se ve son las categorías principales. */
    .chart-container .js-plotly-plot {
        max-height: 15.5cm !important;
        overflow: hidden;
    }

    /* chart-container-scroll ya trae su propio max-height/overflow-y
       "auto" para poder scrollear en pantalla, pero "auto" no recorta
       nada al imprimir (una hoja impresa no tiene scrollbar) — el
       contenido se derrama sobre la tarjeta siguiente. "hidden" sí
       recorta de verdad. */
    .chart-container-scroll {
        max-height: 18cm;
        overflow: hidden;
    }

    /* La tabla de Detalle tiene demasiadas columnas para el ancho de
       A4 y quedaría cortada; esos datos ya tienen su propio botón
       "Exportar a PDF/Excel" (con paginación correcta), así que en
       la vista impresa se oculta en vez de imprimirse recortada. */
    .card:has(.dash-spreadsheet-container) {
        display: none !important;
    }

    .section-label:has(+ .card .dash-spreadsheet-container) {
        display: none !important;
    }
}
