﻿/* ============================================================================
   ReparaHogar - Paleta e identidad visual
   Colores tomados del logo ReparaHogar.png (azul marino + dorado).
   Complemento de Argon Dashboard: solo agrega utilidades de marca.
   ========================================================================== */

:root {
    --repara-azul: #1B2A57;
    --repara-azul-oscuro: #14203F;
    --repara-azul-claro: #2E4483;
    --repara-dorado: #E0A83C;
    --repara-dorado-oscuro: #C68E26;
    --repara-dorado-claro: #F3CE86;
    --repara-gris: #F5F6FA;
    --repara-texto: #35415E;
}

/* ── Texto y fondos ─────────────────────────────────────────────────────── */
.text-repara-azul {
    color: var(--repara-azul) !important;
}

.text-repara-dorado {
    color: var(--repara-dorado) !important;
}

.bg-repara-azul {
    background-color: var(--repara-azul) !important;
}

.bg-repara-gris {
    background-color: var(--repara-gris) !important;
}

.bg-repara-gradient {
    background-image: linear-gradient(310deg, var(--repara-azul-oscuro) 0%, var(--repara-azul-claro) 100%) !important;
}

/* ── Botones ────────────────────────────────────────────────────────────── */
.btn-repara {
    background-color: var(--repara-azul);
    border: 1px solid var(--repara-azul);
    color: #fff;
    box-shadow: 0 4px 10px rgba(27, 42, 87, .25);
    transition: background-color .2s ease, border-color .2s ease, box-shadow .2s ease, color .2s ease;
}

    .btn-repara:hover,
    .btn-repara:focus {
        background-color: var(--repara-dorado);
        border-color: var(--repara-dorado-oscuro);
        color: var(--repara-azul-oscuro);
        box-shadow: 0 4px 12px rgba(224, 168, 60, .35);
    }

    .btn-repara:active {
        background-color: var(--repara-azul-oscuro) !important;
        border-color: var(--repara-azul-oscuro) !important;
        color: #fff !important;
    }

.btn-repara-dorado {
    background-color: var(--repara-dorado);
    border: 1px solid var(--repara-dorado);
    color: var(--repara-azul-oscuro);
    font-weight: 600;
    box-shadow: 0 4px 10px rgba(224, 168, 60, .3);
    transition: background-color .2s ease, border-color .2s ease, box-shadow .2s ease, color .2s ease;
}

    .btn-repara-dorado:hover,
    .btn-repara-dorado:focus {
        background-color: var(--repara-dorado-oscuro);
        border-color: var(--repara-dorado-oscuro);
        color: #fff;
    }

.btn-repara-outline {
    background-color: transparent;
    border: 1px solid var(--repara-azul);
    color: var(--repara-azul);
    transition: background-color .2s ease, color .2s ease;
}

    .btn-repara-outline:hover,
    .btn-repara-outline:focus {
        background-color: var(--repara-azul);
        color: #fff;
    }

/* ── Enlaces y controles ────────────────────────────────────────────────── */
.link-repara {
    color: var(--repara-azul);
    transition: color .2s ease;
}

    .link-repara:hover {
        color: var(--repara-dorado-oscuro);
    }

.form-check-input:checked {
    background-color: var(--repara-azul);
    border-color: var(--repara-azul);
}

.form-control:focus {
    border-color: var(--repara-azul-claro);
    box-shadow: 0 0 0 2px rgba(46, 68, 131, .15);
}

/* ══════════════════════════════════════════════════════════════════════
   Modales de administración (Tipos de Servicio, Clientes, …)
   Formato común: cabecera con degradado sobre foto, etiquetas con icono
   dorado y tabla de detalle. Se comparte para que todos los catálogos
   se vean igual.
   ══════════════════════════════════════════════════════════════════════ */

.modal-repara {
    border: 0;
    border-radius: 1rem;
    overflow: hidden;
}

/* La foto de fondo se declara en el atributo style del propio encabezado,
   detrás del degradado de marca. */
.modal-repara-header {
    color: #fff;
    border-bottom: 0;
    align-items: flex-start;
    padding: 1.25rem 1.5rem;
    background-color: var(--repara-azul-oscuro);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

    .modal-repara-header .modal-title {
        color: #fff;
        font-weight: 700;
        margin-bottom: .25rem;
    }

.modal-repara-sub {
    color: rgba(255, 255, 255, .85);
    font-size: .8rem;
}

.modal-repara-badge {
    background-color: rgba(255, 255, 255, .18);
    color: #fff;
    font-size: .62rem;
    letter-spacing: .06em;
    vertical-align: middle;
}

.modal-repara-label {
    font-size: .75rem;
    font-weight: 700;
    color: var(--repara-azul);
    margin-bottom: .35rem;
    display: block;
}

    .modal-repara-label i {
        color: var(--repara-dorado);
        margin-right: .35rem;
    }

/* ── Atenuado uniforme al abrir un modal ──────────────────────────────
   Toda la pantalla debe oscurecerse de una sola vez. Para eso el fondo
   oscuro tiene que quedar por encima de TODO desde el primer fotograma:
   una sola capa que se desvanece cubre menú, barra superior y contenido
   al mismo tiempo, sin escalones.

   Los valores van por encima de 99999, que es el z-index más alto que usa
   Argon: con 1090 se empataba con reglas propias del tema y el resultado
   dependía del orden de las hojas.

   Orden de la pila, de abajo hacia arriba:
     100000  .modal-backdrop   fondo oscuro que atenúa la página
     100001  .modal            el diálogo
     100002  .loader-container el loader (debe tapar el botón Guardar)
     100003  .swal2-container  los avisos de SweetAlert2

   SweetAlert2 va arriba del todo a propósito: sus mensajes se disparan
   con el modal abierto —por ejemplo al avisar que el usuario ya existe—
   y deben verse y poder cerrarse sin importar qué haya debajo. */
.modal-backdrop {
    z-index: 100000 !important;
}

.modal {
    z-index: 100001 !important;
}

.swal2-container {
    z-index: 100003 !important;
}

/* La barra superior necesita un contexto propio: Argon da z-index 9999 a
   su .navbar-nav. El nivel debe superar los paneles y los canvas de Chart.js
   para que el desplegable de notificaciones no quede detrás de una gráfica,
   pero mantenerse por debajo de los modales (100000). */
.navbar-main {
    position: relative;
    /* Debe superar los controles flotantes de Select2, DataTables y los
       paneles del tablero; los modales empiezan en 100000, así que el menú
       todavía queda correctamente debajo de ellos. */
    z-index: 99998;
}

.navbar-main .campana-panel {
    z-index: 99999 !important;
}

/* ── Modales más altos que la pantalla ───────────────────────────────
   El diálogo nunca debe salirse del viewport. Con .modal-dialog-scrollable
   la cabecera y el pie quedan fijos y el cuerpo se desplaza, que es lo
   deseable: el botón Guardar siempre queda a la vista.

   El contenedor del modal también se deja desplazable como red de
   seguridad para el contenido que no pueda encogerse (tablas anchas,
   pantallas muy bajas). */
.modal {
    overflow-x: hidden;
    overflow-y: auto;
}

/* El <form> de los modales de alta/edición envuelve al cuerpo y al pie, y
   rompía la cadena de flexbox de la que depende .modal-dialog-scrollable:
   .modal-content es un flex column con max-height, pero su hijo pasaba a ser
   el formulario —un bloque normal que crece con su contenido—, así que el
   cuerpo nunca se encogía ni desbordaba y no había nada que desplazar; el
   sobrante quedaba recortado por el overflow:hidden de .modal-content.
   Metiendo el formulario en la cadena, el cuerpo vuelve a encogerse y a
   generar su propia barra de desplazamiento. */
.modal-content.modal-repara > form {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

.modal-repara .modal-body {
    overflow-y: auto;
    /* min-height:0 es imprescindible: sin él un hijo flex no puede encogerse
       por debajo del alto de su contenido y el scroll no aparece. */
    min-height: 0;
    /* Evita que al llegar al final del cuerpo el scroll se contagie
       a la página que está detrás del modal. */
    overscroll-behavior: contain;
}

.modal-repara .modal-footer {
    flex-shrink: 0;
}

/* En pantallas bajas (portátiles pequeños, ventana reducida, móvil en
   horizontal) el centrado vertical reparte el recorte arriba y abajo y
   deja el cuerpo sin altura útil. Ahí conviene anclar el diálogo arriba
   y aprovechar todo el alto disponible. */
@media (max-height: 720px) {
    .modal-dialog-centered {
        align-items: flex-start;
    }

    .modal-dialog {
        margin-top: .75rem;
        margin-bottom: .75rem;
    }

    .modal-dialog-scrollable .modal-content {
        max-height: calc(100vh - 1.5rem);
    }

    /* La cabecera se compacta para devolverle alto al contenido. */
    .modal-repara-header {
        padding: .85rem 1.25rem;
    }
}

/* ── Tablas de detalle dentro de los modales ─────────────────────────── */
.tabla-repara thead th {
    background-color: var(--repara-gris);
    color: var(--repara-azul);
}

.tabla-repara td {
    font-size: .8rem;
    vertical-align: middle;
}

/* ── Icono identificador en los listados ────────────────────────────── */
.icono-repara {
    width: 38px;
    height: 38px;
    border-radius: .6rem;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--repara-dorado);
    background-image: linear-gradient(310deg, var(--repara-azul-oscuro) 0%, var(--repara-azul-claro) 100%);
    flex-shrink: 0;
}

/* ══════════════════════════════════════════════════════════════════════
   Skeleton de carga para los listados
   Al refrescar una tabla se sustituyen las filas por bloques animados en
   lugar de recargar la página: el cambio se percibe como una transición
   y no como un parpadeo.
   ══════════════════════════════════════════════════════════════════════ */

.skeleton-bloque {
    display: block;
    height: .75rem;
    border-radius: .35rem;
    background-color: #e9ecef;
    background-image: linear-gradient(90deg, #e9ecef 0%, #f5f6fa 50%, #e9ecef 100%);
    background-size: 200% 100%;
    animation: skeleton-brillo 1.2s ease-in-out infinite;
}

    .skeleton-bloque + .skeleton-bloque {
        margin-top: .4rem;
    }

.skeleton-circulo {
    width: 38px;
    height: 38px;
    border-radius: .6rem;
    flex-shrink: 0;
}

@keyframes skeleton-brillo {
    0% {
        background-position: 200% 0;
    }

    100% {
        background-position: -200% 0;
    }
}

/* Sin animación para quien la haya desactivado en su sistema. */
@media (prefers-reduced-motion: reduce) {
    .skeleton-bloque {
        animation: none;
    }
}

/* Entrada suave de las filas recién cargadas. */
.tabla-actualizada > tr {
    animation: repara-aparecer .35s ease-out both;
}

@keyframes repara-aparecer {
    from {
        opacity: 0;
        transform: translateY(-4px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .tabla-actualizada > tr {
        animation: none;
    }
}

/* ══════════════════════════════════════════════════════════════════════
   Animación de los avisos (SweetAlert2)
   Reemplaza el rebote por omisión por una entrada y salida suaves; las
   clases se declaran en assets/js/repara-avisos.js.
   ══════════════════════════════════════════════════════════════════════ */

.repara-aviso-entra {
    animation: repara-aviso-entrada .22s ease-out both;
}

.repara-aviso-sale {
    animation: repara-aviso-salida .16s ease-in both;
}

.repara-fondo-entra {
    animation: repara-fondo-entrada .22s ease-out both;
}

.repara-fondo-sale {
    animation: repara-fondo-salida .16s ease-in both;
}

@keyframes repara-aviso-entrada {
    from {
        opacity: 0;
        transform: translateY(-8px) scale(.98);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes repara-aviso-salida {
    from {
        opacity: 1;
        transform: none;
    }

    to {
        opacity: 0;
        transform: scale(.98);
    }
}

@keyframes repara-fondo-entrada {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes repara-fondo-salida {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .repara-aviso-entra,
    .repara-aviso-sale,
    .repara-fondo-entra,
    .repara-fondo-sale {
        animation: none;
    }
}

/* ══════════════════════════════════════════════════════════════════════
   Acceso con proveedores externos (Google)
   ══════════════════════════════════════════════════════════════════════ */

.btn-google {
    background-color: #fff;
    border: 1px solid #d2d6da;
    color: #3c4043;
    font-weight: 600;
    transition: box-shadow .2s ease, border-color .2s ease;
}

    .btn-google:hover,
    .btn-google:focus {
        border-color: #b9bec4;
        box-shadow: 0 2px 8px rgba(0, 0, 0, .12);
        color: #3c4043;
    }

/* Separador "o continúe con" entre el formulario y el botón externo. */
.separador-o {
    display: flex;
    align-items: center;
    gap: .75rem;
    color: #8392AB;
    font-size: .75rem;
    margin: 1.1rem 0;
}

    .separador-o::before,
    .separador-o::after {
        content: "";
        flex: 1;
        height: 1px;
        background-color: #e9ecef;
    }

/* Botón externo inhabilitado: se ve, pero se nota que aún no está activo. */
.btn-google:disabled,
.btn-google.disabled {
    opacity: .55;
    cursor: not-allowed;
    box-shadow: none;
}

/* ══════════════════════════════════════════════════════════════════════
   TABLAS AGRUPADAS POR FILAS (DataTables + RowGroup)
   ----------------------------------------------------------------------
   Cabecera de cada grupo y ajustes de los controles de DataTables al
   aspecto del resto del sistema. Lo usan los listados que agrupan por una
   columna repetida (Clientes por ubicación, Usuarios por rol, Servicios
   por tipo, Técnicos por contratación, Municipios por departamento).
   El comportamiento vive en assets/js/repara-tabla-agrupada.js.
   ══════════════════════════════════════════════════════════════════════ */

.tabla-agrupada tr.dtrg-group td {
    background-image: linear-gradient(310deg, var(--repara-azul-oscuro) 0%, var(--repara-azul-claro) 100%);
    color: #fff;
    font-weight: 700;
    font-size: .8rem;
    letter-spacing: .02em;
    padding: .55rem 1rem;
    border: 0;
}

    .tabla-agrupada tr.dtrg-group td i {
        color: var(--repara-dorado);
        margin-right: .4rem;
    }

    .tabla-agrupada tr.dtrg-group td .contador-grupo {
        background-color: rgba(255, 255, 255, .18);
        border-radius: 1rem;
        font-size: .68rem;
        font-weight: 600;
        padding: .1rem .55rem;
        margin-left: .5rem;
    }

/* Segundo nivel de agrupación, cuando la pantalla lo declara (Órdenes de
   Servicio: municipio y, dentro, cada orden).

   Se dibuja como una cabecera menor y no como otra franja azul: dos bandas del
   mismo peso una encima de otra compiten, y el municipio dejaría de leerse como
   el marco que contiene a las órdenes. Aquí basta con una tira clara,
   sangrada, que diga dónde empieza cada orden. */
.tabla-agrupada tr.dtrg-level-1 td {
    background-image: none;
    background-color: #eef1f8;
    color: var(--repara-azul);
    font-size: .76rem;
    padding: .35rem 1rem .35rem 1.75rem;
    border-bottom: 1px solid #e3e6ef;
}

    .tabla-agrupada tr.dtrg-level-1 td i {
        color: var(--repara-azul-claro);
    }

    .tabla-agrupada tr.dtrg-level-1 td .contador-grupo {
        background-color: rgba(27, 42, 87, .10);
        color: var(--repara-azul);
    }

/* Las filas se indentan bajo la cabecera de su grupo. Con dos niveles la
   sangría crece un escalón más, para que se vea que la fila cuelga de la
   orden y la orden del municipio. */
.tabla-agrupada tbody tr:not(.dtrg-group) > td:first-child {
    padding-left: 1.75rem;
}

.tabla-agrupada.tabla-subagrupada tbody tr:not(.dtrg-group) > td:first-child {
    padding-left: 2.75rem;
}

/* Controles de DataTables con el aspecto del resto del sistema.

   La hoja seleccionada se pinta sobre el azul de marca, así que su número va
   en blanco. DataTables trae un `color: inherit !important` en
   `div.dt-container .dt-paging .dt-paging-button.current`, que por llevar un
   elemento en el selector pesa más que la regla de aquí y dejaba el número en
   gris sobre el azul. Por eso se repiten los mismos elementos y se cubren
   además hover/foco/activo, que la librería reescribe por separado. */
div.dt-container div.dt-paging .dt-paging-button.current,
div.dt-container div.dt-paging .dt-paging-button.current:hover,
div.dt-container div.dt-paging .dt-paging-button.current:focus,
div.dt-container div.dt-paging .dt-paging-button.current:active,
div[id$="_wrapper"] div.dt-paging .dt-paging-button.current,
div[id$="_wrapper"] div.dt-paging .dt-paging-button.current:hover,
div[id$="_wrapper"] div.dt-paging .dt-paging-button.current:focus,
div[id$="_wrapper"] div.dt-paging .dt-paging-button.current:active {
    background: var(--repara-azul) !important;
    border-color: var(--repara-azul) !important;
    color: #fff !important;
}

div[id$="_wrapper"] .dt-info,
div[id$="_wrapper"] .dt-length {
    font-size: .8rem;
    color: var(--repara-texto);
}

    div[id$="_wrapper"] .dt-length select {
        border: 1px solid #d2d6da;
        border-radius: .4rem;
        padding: .15rem 1.4rem .15rem .4rem;
    }

/* ══════════════════════════════════════════════════════════════════════
   MI CUENTA

   Ficha de la cuenta del usuario, en el modal que abre el ícono de la
   barra superior. Vive aquí y no en una vista porque el modal se monta
   en el layout del panel: está presente en todas las pantallas.

   La ficha es una lista de filas "icono · etiqueta · valor · acción",
   que se lee de un vistazo y deja el detalle a la derecha.
   ══════════════════════════════════════════════════════════════════════ */

/* Avatar con las iniciales. Toma el degradado de marca en lugar de un
   color plano para que combine con la cabecera del propio modal. */
.cuenta-avatar {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background-image: linear-gradient(310deg, var(--repara-azul-oscuro) 0%, var(--repara-azul-claro) 100%);
    color: #fff;
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: .04em;
}

/* La caja que sostiene al avatar y a su botón. Existe para que el botón se
   pueda montar sobre la esquina: sin un contenedor posicionado, quedaría
   anclado al diálogo y se movería con el contenido. */
.cuenta-avatar-caja {
    position: relative;
    flex-shrink: 0;
    width: 72px;
    height: 72px;
}

/* La foto tapa a las iniciales en vez de sustituirlas en el marcado: así
   volver a "sin foto" es quitar una clase, y no rehacer el bloque. */
.cuenta-avatar-foto {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
    background-color: #eef1f8;
}

/* Sobre la esquina inferior derecha, con borde blanco para despegarlo del
   avatar: es el sitio donde se busca cambiar una foto. */
.cuenta-avatar-boton {
    position: absolute;
    right: -2px;
    bottom: -2px;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 2px solid #fff;
    background-image: linear-gradient(310deg, var(--repara-dorado-oscuro) 0%, var(--repara-dorado) 100%);
    color: var(--repara-azul-oscuro);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .72rem;
    cursor: pointer;
    margin: 0;
    /* Dejó de ser una etiqueta para ser un botón: sin esto el relleno propio
       del control descentra el icono, y Safari le pinta encima su propio
       aspecto de botón. */
    padding: 0;
    line-height: 1;
    -webkit-appearance: none;
    appearance: none;
}

    .cuenta-avatar-boton:hover {
        filter: brightness(1.06);
    }

.cuenta-quitar-foto {
    border: 0;
    background: none;
    padding: 0;
    font-size: .72rem;
    font-weight: 600;
    color: #a4302b;
}

/* ── De dónde sale la foto ────────────────────────────────────────────
   Dos opciones del mismo tamaño y con el mismo peso: tomar una foto es tan
   normal como buscarla en el disco, y una de las dos dibujada como secundaria
   empuja a la otra. */
.cuenta-foto-menu {
    display: flex;
    gap: .6rem;
    margin: -.75rem 0 1.25rem;
}

.cuenta-foto-opcion {
    flex: 1 1 0;
    min-height: 58px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .2rem;
    border: 1px solid #dde2ec;
    border-radius: .7rem;
    background-color: #fff;
    color: var(--repara-azul);
    font-size: .76rem;
    font-weight: 700;
}

    .cuenta-foto-opcion i {
        font-size: 1.05rem;
        color: var(--repara-dorado);
    }

    .cuenta-foto-opcion:hover {
        background-color: #f4f6fb;
    }

/* ── La cámara ────────────────────────────────────────────────────────
   El recuadro es CUADRADO y lleva una máscara redonda encima porque el avatar
   es un círculo: con una vista previa rectangular, lo que se enmarca al posar
   no es lo que después se ve. */
.cuenta-camara {
    margin: -.75rem 0 1.25rem;
}

.cuenta-camara-marco {
    position: relative;
    width: 100%;
    max-width: 260px;
    margin: 0 auto;
    aspect-ratio: 1 / 1;
    border-radius: 1rem;
    overflow: hidden;
    background-color: #14203f;
}

    .cuenta-camara-marco video {
        width: 100%;
        height: 100%;
        object-fit: cover;
        display: block;
        /* Espejada, como un espejo de verdad: sin esto, moverse a la derecha se
           ve a la izquierda y encuadrarse cuesta. Lo que se guarda va espejado
           igual, para que la foto sea la que se estaba viendo. */
        transform: scaleX(-1);
    }

/* El círculo que anticipa el recorte del avatar: lo de fuera se oscurece. */
.cuenta-camara-mascara {
    position: absolute;
    inset: 0;
    pointer-events: none;
    box-shadow: inset 0 0 0 2000px rgba(20, 32, 63, .45);
    -webkit-mask-image: radial-gradient(circle at 50% 50%, transparent 48%, #000 48.5%);
    mask-image: radial-gradient(circle at 50% 50%, transparent 48%, #000 48.5%);
}

.cuenta-camara-botones {
    display: flex;
    justify-content: center;
    gap: .6rem;
    margin-top: .8rem;
}

.cuenta-camara-aviso {
    display: block;
    text-align: center;
    font-size: .74rem;
    color: #5b6478;
    margin-top: .5rem;
}

    .cuenta-quitar-foto:hover {
        text-decoration: underline;
    }

.cuenta-fila {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: .85rem 0;
    border-bottom: 1px solid #f0f2f7;
}

    /* La última fila no lleva separador: cerraría la lista con una línea
       suelta justo encima del pie del modal. */
    .cuenta-fila:last-child {
        border-bottom: 0;
    }

.cuenta-icono {
    width: 40px;
    height: 40px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background-color: #eef1fa;
    color: var(--repara-azul);
}

/* min-width:0 es imprescindible: sin él un hijo flex no se encoge por
   debajo de su contenido y un correo largo desborda la fila en lugar de
   recortarse. */
.cuenta-cuerpo {
    flex: 1 1 auto;
    min-width: 0;
}

.cuenta-etiqueta {
    display: block;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #8a93a6;
    margin-bottom: .1rem;
}

.cuenta-valor {
    display: block;
    font-size: .95rem;
    color: var(--repara-texto);
    word-break: break-word;
}

/* Botón de acción de la fila (editar, cambiar contraseña): discreto
   mientras no se necesita, de marca al apuntarlo. */
.cuenta-accion {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 1px solid #dbe0ec;
    background: transparent;
    color: var(--repara-azul);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

    .cuenta-accion:hover {
        background-color: var(--repara-azul);
        border-color: var(--repara-azul);
        color: #fff;
    }

/* Los campos editables comparten sitio con el valor: el formulario
   aparece donde estaba el texto, sin desplazar el resto de la ficha. */
.cuenta-edicion {
    display: none;
}

.cuenta-fila.editando .cuenta-valor {
    display: none;
}

.cuenta-fila.editando .cuenta-edicion {
    display: block;
}

.cuenta-fila.editando .cuenta-icono {
    background-color: var(--repara-dorado-claro);
    color: var(--repara-azul-oscuro);
}

/* ══════════════════════════════════════════════════════════════════════
   PANEL DE NAVEGACIÓN (modalSelectOptionMenu)

   Mosaico de accesos a los dashboards, en carrusel: solo se ve una
   sección a la vez, de modo que el modal conserva su tamaño en lugar de
   alargarse conforme se agreguen paneles.

   Vive aquí y no en una vista porque el modal se monta en el layout del
   panel: está presente en todas las pantallas.
   ══════════════════════════════════════════════════════════════════════ */

/* ── Tamaño constante y centrado ──────────────────────────────────────
   El panel cambiaba de tamaño según la sección abierta del carrusel
   —"Paneles principales" trae dos filas de mosaicos y "Auditoría" una
   sola—, de modo que al pasar de una a otra el modal crecía o se encogía
   y los controles se movían bajo el cursor. Y al reducir el alto de la
   ventana por debajo de 720px la regla general de arriba lo anclaba al
   borde superior en lugar de dejarlo centrado.

   Se le fija el ancho y el alto: el contenido ya no manda sobre la caja,
   sino al revés. Solo cede cuando la ventana es más pequeña que él, para
   no quedar recortado. */
.selopt-dialog {
    width: 640px;
    max-width: calc(100vw - 1rem);
}

.selopt-modal {
    border-radius: 1rem;
    overflow: hidden;
    height: 32rem;
    max-height: 100%;
}

@media (max-height: 720px) {
    /* Excepción a la regla general: este modal no necesita anclarse
       arriba porque su alto es fijo y modesto, así que sigue centrado. */
    .modal-dialog-centered.selopt-dialog {
        align-items: center;
    }
}

.selopt-header {
    background-image: linear-gradient(310deg, var(--repara-azul-oscuro) 0%, var(--repara-azul-claro) 100%);
    padding: 1.25rem 1.5rem;
    align-items: center;
}

.selopt-header-icon {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background-color: rgba(255, 255, 255, .16);
    color: var(--repara-dorado);
    font-size: 1.1rem;
}

.selopt-header-sub {
    color: rgba(255, 255, 255, .75);
    font-size: .78rem;
}

.selopt-body {
    padding: 1.25rem 1.5rem .5rem;
    /* Columna flexible para que el carrusel ocupe el alto sobrante del
       modal en vez de dictarlo. min-height:0 es imprescindible: sin él un
       hijo flex no puede encogerse por debajo de su contenido. */
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* Encabezado de cada sección del carrusel. */
.selopt-group-head {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin-bottom: .9rem;
}

.selopt-group-icon {
    width: 34px;
    height: 34px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background-color: #eef1fa;
    color: var(--repara-azul);
    font-size: .85rem;
}

.selopt-group-titles {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.selopt-group-title {
    font-size: .9rem;
    font-weight: 700;
    color: var(--repara-azul);
    line-height: 1.2;
}

.selopt-group-sub {
    font-size: .72rem;
    color: #8a93a6;
}

/* ── Mosaico ──────────────────────────────────────────────────────── */
.selopt-tile {
    position: relative;
    display: flex;
    align-items: center;
    gap: .75rem;
    height: 100%;
    min-height: 84px;
    padding: .85rem 2rem .85rem .85rem;
    border: 1px solid #e3e6ef;
    border-radius: .85rem;
    background-color: #fff;
    overflow: hidden;
    text-decoration: none;
    transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

    .selopt-tile:hover {
        border-color: var(--repara-azul-claro);
        box-shadow: 0 .5rem 1rem rgba(20, 32, 63, .12);
        transform: translateY(-2px);
        text-decoration: none;
    }

/* Icono de marca de agua: da identidad al mosaico sin competir con el
   texto, por eso va muy atenuado y recortado por el borde. */
.selopt-tile-bg {
    position: absolute;
    right: -.5rem;
    bottom: -1rem;
    font-size: 3.5rem;
    color: var(--repara-azul);
    opacity: .05;
    pointer-events: none;
}

.selopt-tile-icon {
    width: 42px;
    height: 42px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background-image: linear-gradient(310deg, var(--repara-azul-oscuro) 0%, var(--repara-azul-claro) 100%);
    color: #fff;
    font-size: 1rem;
}

.selopt-tile-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.selopt-tile-title {
    font-size: .88rem;
    font-weight: 700;
    color: var(--repara-azul);
    line-height: 1.25;
}

.selopt-tile-desc {
    font-size: .72rem;
    color: #8a93a6;
    line-height: 1.3;
}

.selopt-tile-arrow {
    position: absolute;
    right: .75rem;
    top: 50%;
    transform: translateY(-50%);
    color: #c7cddd;
    font-size: .75rem;
    transition: color .15s ease, right .15s ease;
}

.selopt-tile:hover .selopt-tile-arrow {
    color: var(--repara-dorado);
    right: .55rem;
}

/* Distintivo del panel al que se entra por omisión al iniciar sesión. */
.selopt-tile-default {
    position: absolute;
    top: .4rem;
    right: .4rem;
    padding: .1rem .45rem;
    border-radius: 1rem;
    background-color: var(--repara-dorado);
    color: var(--repara-azul-oscuro);
    font-size: .6rem;
    font-weight: 700;
    letter-spacing: .03em;
}

/* Variantes por área: solo cambia el degradado del icono, para que los
   mosaicos se distingan de un vistazo sin romper la paleta. */
.selopt-tile--admin .selopt-tile-icon {
    background-image: linear-gradient(310deg, var(--repara-azul-oscuro) 0%, var(--repara-azul-claro) 100%);
}

.selopt-tile--despachador .selopt-tile-icon {
    background-image: linear-gradient(310deg, #7B5E10 0%, var(--repara-dorado) 100%);
}

.selopt-tile--tecnico .selopt-tile-icon {
    background-image: linear-gradient(310deg, #14503F 0%, #2E8B6F 100%);
}

.selopt-tile--cliente .selopt-tile-icon {
    background-image: linear-gradient(310deg, #4A2A6B 0%, #7B52A8 100%);
}

.selopt-tile--proceso .selopt-tile-icon {
    background-image: linear-gradient(310deg, #5A3010 0%, #B5651D 100%);
}

.selopt-tile--web .selopt-tile-icon {
    background-image: linear-gradient(310deg, #10475A 0%, #2E8BA8 100%);
}

.selopt-tile--whatsapp .selopt-tile-icon {
    background-image: linear-gradient(310deg, #128C7E 0%, #25D366 100%);
}

/* Panel que todavía no existe: se muestra para dejar ver el mapa completo
   del sistema, pero no es un enlace. Sin esto habría que elegir entre
   ocultarlo —y que nadie sepa que está previsto— o enlazar a una página
   que no está y devolver un 404. */
.selopt-tile--pendiente {
    background-color: #fafbfd;
    border-style: dashed;
    cursor: not-allowed;
}

    .selopt-tile--pendiente:hover {
        border-color: #e3e6ef;
        box-shadow: none;
        transform: none;
    }

    .selopt-tile--pendiente .selopt-tile-icon {
        background-image: none;
        background-color: #dfe3ee;
        color: #98a1b5;
    }

    .selopt-tile--pendiente .selopt-tile-title {
        color: #8a93a6;
    }

/* ── Carrusel ─────────────────────────────────────────────────────── */
.selopt-carousel {
    padding: 0 1.75rem 2.25rem;
    margin: 0 -1rem;
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

    /* La sección visible ocupa siempre el mismo hueco, pase el carrusel
       por la que traiga más mosaicos o por la que traiga menos. Si alguna
       no cabe —en pantallas angostas los mosaicos se apilan— se desplaza
       ella sola; el modal no se estira. */
    .selopt-carousel .carousel-inner {
        flex: 1 1 auto;
        min-height: 0;
        overflow-x: hidden;
        overflow-y: auto;
        overscroll-behavior: contain;
    }

/* Los controles se colocan sobre los márgenes laterales que reserva el
   relleno de arriba, para que no tapen los mosaicos. */
.selopt-carousel-ctrl {
    width: 1.75rem;
    opacity: .45;
}

    .selopt-carousel-ctrl:hover {
        opacity: 1;
    }

    /* Los iconos de Bootstrap son blancos: sobre fondo claro no se ven. */
    .selopt-carousel-ctrl .carousel-control-prev-icon,
    .selopt-carousel-ctrl .carousel-control-next-icon {
        filter: invert(1) grayscale(1) brightness(.4);
        width: 1.1rem;
        height: 1.1rem;
    }

.selopt-carousel-dots {
    bottom: .25rem;
    margin-bottom: 0;
}

    .selopt-carousel-dots button {
        width: 8px !important;
        height: 8px !important;
        border-radius: 50%;
        background-color: #c7cddd !important;
        border: 0;
        opacity: 1;
    }

        .selopt-carousel-dots button.active {
            background-color: var(--repara-azul) !important;
        }

/* ── WhatsApp de la empresa ───────────────────────────────────────── */
.selopt-whatsapp {
    border: 1px solid #e3e6ef;
    border-radius: .85rem;
    padding: .85rem;
    background-color: #fff;
}

.selopt-whatsapp-numero {
    font-size: 1rem;
    font-weight: 700;
    color: var(--repara-azul);
    letter-spacing: .02em;
}

.selopt-footer {
    padding: .85rem 1.5rem 1.15rem;
    background-color: #fafbfd;
}

/* ══════════════════════════════════════════════════════════════════════
   BOTONES FLOTANTES DEL PANEL

   Pila fija en la esquina inferior derecha: WhatsApp arriba y, debajo, el
   acceso al panel de navegación. Van flotando y no en la barra superior
   porque son atajos que deben alcanzarse desde cualquier punto de una
   pantalla larga, sin volver arriba.
   ══════════════════════════════════════════════════════════════════════ */

.repara-fab-pila {
    position: fixed;
    right: 1.5rem;
    bottom: 1.5rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .75rem;
    /* Por debajo del atenuado de los modales (100000): con un modal abierto
       los botones no deben quedar iluminados por encima del velo. */
    z-index: 1030;
}

.repara-fab {
    width: 56px;
    height: 56px;
    border: 0;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 1.35rem;
    text-decoration: none;
    box-shadow: 0 .5rem 1.25rem rgba(20, 32, 63, .28);
    transition: transform .15s ease, box-shadow .15s ease, filter .15s ease;
}

    .repara-fab:hover,
    .repara-fab:focus {
        color: #fff;
        transform: translateY(-3px) scale(1.04);
        box-shadow: 0 .75rem 1.5rem rgba(20, 32, 63, .35);
    }

/* El de navegación toma el dorado del logo; es el botón principal y por eso
   va abajo, al alcance del pulgar. */
.repara-fab--menu {
    background-image: linear-gradient(310deg, var(--repara-dorado-oscuro) 0%, var(--repara-dorado) 100%);
    color: var(--repara-azul-oscuro);
}

    .repara-fab--menu:hover,
    .repara-fab--menu:focus {
        color: var(--repara-azul-oscuro);
    }

/* WhatsApp conserva su verde de marca: es el color por el que se reconoce,
   y cambiarlo lo volvería un botón cualquiera. */
.repara-fab--whatsapp {
    background-image: linear-gradient(310deg, #128C7E 0%, #25D366 100%);
}

/* Etiqueta que aparece al apuntar el botón, a su izquierda. */
.repara-fab-tip {
    position: absolute;
    right: 4.25rem;
    white-space: nowrap;
    background-color: var(--repara-azul-oscuro);
    color: #fff;
    font-size: .72rem;
    font-weight: 600;
    padding: .3rem .6rem;
    border-radius: .4rem;
    opacity: 0;
    pointer-events: none;
    transform: translateX(.4rem);
    transition: opacity .15s ease, transform .15s ease;
}

.repara-fab-item {
    position: relative;
    display: flex;
    align-items: center;
}

    .repara-fab-item:hover .repara-fab-tip {
        opacity: 1;
        transform: translateX(0);
    }

/* En pantallas pequeñas los botones se encogen y se pegan más al borde,
   para no taparle al usuario el contenido de la esquina. */
@media (max-width: 575.98px) {
    .repara-fab-pila {
        right: 1rem;
        bottom: 1rem;
        gap: .6rem;
    }

    .repara-fab {
        width: 48px;
        height: 48px;
        font-size: 1.15rem;
    }

    /* La etiqueta sobra donde no hay puntero. */
    .repara-fab-tip {
        display: none;
    }
}
