/* =============================================================================
   TEMA PREMIUM · Centro de Estilismo
   -----------------------------------------------------------------------------
   Apartado 3: estética premium, elegante, minimalista y moderna.
   Referencias: Apple, Stripe, Notion, hotelería boutique.

   Principios aplicados:
     · Mucho espacio en blanco; el vacío es parte del diseño.
     · Paleta neutra (blanco, negro, grises) con UN acento dorado discreto.
     · Bordes sutiles de 1 px en lugar de sombras marcadas.
     · Sombras muy suaves y solo donde hay elevación real.
     · Transiciones cortas (150-250 ms): se perciben, no se esperan.
     · Tipografía del sistema: carga instantánea y aspecto nativo en cada equipo.

   Todo se define con variables CSS para que el administrador pueda cambiar los
   colores desde el panel (apartado 47, mejora M-10) sin recompilar nada.
   ============================================================================= */

:root {
    /* ── Paleta ─────────────────────────────────────────────────────────── */
    --salon-negro:        #111111;
    --salon-negro-suave:  #1D1D1F;
    --salon-gris-900:     #2C2C2E;
    --salon-gris-700:     #48484A;
    --salon-gris-500:     #8E8E93;
    --salon-gris-400:     #AEAEB2;
    --salon-gris-300:     #D1D1D6;
    --salon-gris-200:     #E5E5EA;
    --salon-gris-100:     #F2F2F7;
    --salon-gris-50:      #FAFAFA;
    --salon-blanco:       #FFFFFF;

    /* Acento: dorado champagne, muy discreto */
    --salon-dorado:       #C9B037;
    --salon-dorado-claro: #E3D9A6;
    --salon-champagne:    #F7F3E9;
    --salon-champagne-2:  #EFE7D6;
    /* Texto que va ENCIMA del champán. Existe como variable porque el champán
       cambia con el tema: escrito a mano (#7A6A17) obligaba a que el fondo
       fuese siempre claro, y en oscuro dejaba texto claro sobre crema. */
    --salon-sobre-champagne: #7A6A17;

    /* Botón sólido (acción primaria). En claro es negro sobre blanco; en oscuro
       se INVIERTE a claro sobre negro. Con el negro fijo, en tema oscuro el
       botón quedaba a 1.06:1 contra la superficie: el texto se leía, pero el
       botón desaparecía como forma y no se veía dónde había que pulsar. */
    --salon-boton-solido:       var(--salon-negro);
    --salon-boton-solido-hover: var(--salon-negro-suave);
    --salon-sobre-boton-solido: #FFFFFF;

    /* Estados semánticos (desaturados a propósito) */
    --salon-exito:        #2E7D5B;
    --salon-exito-suave:  #E8F3EE;
    --salon-aviso:        #B7791F;
    --salon-aviso-suave:  #FBF3E4;
    --salon-error:        #B3261E;
    --salon-error-suave:  #FBEAE9;
    --salon-info:         #2C5A78;
    --salon-info-suave:   #E9F1F6;

    /* ── Tokens semánticos (modo claro) ─────────────────────────────────── */
    --salon-fondo:            var(--salon-gris-50);
    --salon-superficie:       var(--salon-blanco);
    --salon-superficie-alta:  var(--salon-blanco);
    --salon-superficie-hover: var(--salon-gris-100);
    --salon-texto:            var(--salon-negro);
    --salon-texto-suave:      var(--salon-gris-700);
    --salon-texto-tenue:      var(--salon-gris-500);
    --salon-borde:            var(--salon-gris-200);
    --salon-borde-fuerte:     var(--salon-gris-300);
    --salon-acento:           var(--salon-dorado);
    --salon-sobre-acento:     var(--salon-negro);

    /* ── Forma y movimiento ─────────────────────────────────────────────── */
    --salon-radio-sm: 8px;
    --salon-radio:    12px;
    --salon-radio-lg: 18px;
    --salon-radio-xl: 24px;

    --salon-sombra-sm: 0 1px 2px rgba(17, 17, 17, .04);
    --salon-sombra:    0 2px 8px rgba(17, 17, 17, .05);
    --salon-sombra-md: 0 8px 24px rgba(17, 17, 17, .07);
    --salon-sombra-lg: 0 16px 48px rgba(17, 17, 17, .10);

    --salon-transicion: 180ms cubic-bezier(.4, 0, .2, 1);
    --salon-transicion-lenta: 280ms cubic-bezier(.4, 0, .2, 1);

    --salon-sidebar-ancho: 260px;
    --salon-topbar-alto:   64px;

    /* ── Estados de reserva (apartado 7) ────────────────────────────────────
       Cada estado tiene su propio color. Se definen aquí, y no en agenda.css,
       porque el dashboard y los reportes muestran los mismos estados y deben
       coincidir: si «confirmada» es verde en el calendario y azul en el
       informe, quien lo lee deja de fiarse del color.

       La paleta general del sistema es neutra a propósito, pero el calendario
       es la única pantalla donde el color TRANSPORTA información en vez de
       decorar. Aquí un tono se gana su sitio si permite distinguir un estado
       de otro de un vistazo, y por eso hay más color que en el resto.
       Aun así se mantienen desaturados y el estado siempre se acompaña de
       texto e icono: el color no es nunca el único portador del dato.        */
    --cita-pendiente-borde:  #B7791F;   /* Ámbar · falta que el cliente confirme */
    --cita-pendiente-fondo:  #FDF4E3;
    --cita-pendiente-texto:  #6E4711;

    --cita-reservada-borde:  #1F4E6B;   /* Azul · agendada en firme */
    --cita-reservada-fondo:  #E8F1F7;
    --cita-reservada-texto:  #1C3B4F;

    --cita-confirmada-borde: #2E7D5B;   /* Verde · el cliente confirmó */
    --cita-confirmada-fondo: #E4F2EB;
    --cita-confirmada-texto: #1B5540;

    --cita-en_camino-borde:  #2E97AD;   /* Turquesa · viene en camino */
    --cita-en_camino-fondo:  #E0F2F6;
    --cita-en_camino-texto:  #0A4D60;

    --cita-atendida-borde:   #7A5AAE;   /* Violeta · atendida, falta cobrar */
    --cita-atendida-fondo:   #EFEAF7;
    --cita-atendida-texto:   #46346B;

    --cita-finalizada-borde: #8E8E93;   /* Gris · cerrada y pagada, ya no pide nada */
    --cita-finalizada-fondo: #F2F2F7;
    --cita-finalizada-texto: #48484A;

    --cita-cancelada-borde:  #B3261E;   /* Rojo · anulada */
    --cita-cancelada-fondo:  #FBEAE9;
    --cita-cancelada-texto:  #7F1B15;

    --cita-no_asistio-borde: #7A1710;   /* Granate · el peor caso, debe saltar a la vista */
    --cita-no_asistio-fondo: #F5DCD9;
    --cita-no_asistio-texto: #5C110C;

    --cita-reagendada-borde: #5F6B7A;   /* Gris azulado · se movió a otra fecha */
    --cita-reagendada-fondo: #ECEFF3;
    --cita-reagendada-texto: #3E4753;

    --cita-bloqueo-borde:    #AEAEB2;   /* Neutro · no es una cita */
    --cita-bloqueo-fondo:    #F2F2F7;

    /* Bootstrap: se reasignan sus variables para no pelear con el framework */
    --bs-body-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                           "Helvetica Neue", "Inter", Arial, sans-serif;
    --bs-body-bg:    var(--salon-fondo);
    --bs-body-color: var(--salon-texto);
    --bs-border-color: var(--salon-borde);
    --bs-primary: var(--salon-negro);
    --bs-link-color: var(--salon-negro);
    --bs-link-hover-color: var(--salon-dorado);
    --bs-border-radius: var(--salon-radio);
    --bs-border-radius-sm: var(--salon-radio-sm);
    --bs-border-radius-lg: var(--salon-radio-lg);
}

/* ── Modo oscuro (mejora M-11) ──────────────────────────────────────────────
   Se respeta la preferencia del sistema y además se admite forzarlo con el
   atributo data-tema, que es lo que usa el interruptor de la barra superior. */
@media (prefers-color-scheme: dark) {
    :root:not([data-tema="claro"]) {
        --salon-fondo:            #0B0B0C;
        --salon-superficie:       #161618;
        --salon-superficie-alta:  #1F1F22;
        --salon-superficie-hover: #232326;
        --salon-texto:            #F5F5F7;
        --salon-texto-suave:      #C7C7CC;
        --salon-texto-tenue:      #8E8E93;
        --salon-borde:            #2C2C2E;
        --salon-borde-fuerte:     #3A3A3C;
        --salon-sobre-acento:     #111111;

        /* El champán en oscuro deja de ser crema y pasa a dorado apagado; si no,
           cualquier fondo de acento queda casi blanco bajo texto claro, que es
           justo lo que ocultaba los nombres de los profesionales en la agenda. */
        --salon-champagne:       #2A2517;
        --salon-champagne-2:     #3A3220;
        --salon-sobre-champagne: #E3D9A6;
        --salon-boton-solido:       #F5F5F7;
        --salon-boton-solido-hover: #DCDCE0;
        --salon-sobre-boton-solido: #0B0B0C;

        --salon-exito-suave: #12271F;
        --salon-aviso-suave: #2A2114;
        --salon-error-suave: #2A1614;
        --salon-info-suave:  #12212B;

        --salon-sombra-sm: 0 1px 2px rgba(0, 0, 0, .4);
        --salon-sombra:    0 2px 8px rgba(0, 0, 0, .45);
        --salon-sombra-md: 0 8px 24px rgba(0, 0, 0, .5);
        --salon-sombra-lg: 0 16px 48px rgba(0, 0, 0, .6);

        /* Estados de reserva: mismos tonos que en `[data-tema="oscuro"]`. Hay
           que repetirlos aquí porque este bloque atiende a quien tiene el
           sistema en oscuro y NO ha tocado el interruptor; sin esto vería
           tarjetas claras sobre fondo negro.                                */
        --cita-pendiente-borde:  #D9A441;
        --cita-pendiente-fondo:  #2E2312;
        --cita-pendiente-texto:  #F0D9A8;

        --cita-reservada-borde:  #5E9BC0;
        --cita-reservada-fondo:  #12242F;
        --cita-reservada-texto:  #B9DCEF;

        --cita-confirmada-borde: #4FA97F;
        --cita-confirmada-fondo: #12281F;
        --cita-confirmada-texto: #A9E2C4;

        --cita-en_camino-borde:  #3AA6BF;
        --cita-en_camino-fondo:  #0F272E;
        --cita-en_camino-texto:  #A5DDEA;

        --cita-atendida-borde:   #9B7ED1;
        --cita-atendida-fondo:   #201A2E;
        --cita-atendida-texto:   #CFC0EC;

        --cita-finalizada-borde: #6E6E73;
        --cita-finalizada-fondo: #1E1E21;
        --cita-finalizada-texto: #B4B4B9;

        --cita-cancelada-borde:  #D4564D;
        --cita-cancelada-fondo:  #2C1614;
        --cita-cancelada-texto:  #F0B5B0;

        --cita-no_asistio-borde: #E2685C;
        --cita-no_asistio-fondo: #3A1512;
        --cita-no_asistio-texto: #F7C3BD;

        --cita-reagendada-borde: #8794A3;
        --cita-reagendada-fondo: #1D2126;
        --cita-reagendada-texto: #C3CCD6;

        --cita-bloqueo-borde:    #4A4A4E;
        --cita-bloqueo-fondo:    #1C1C1F;

        --bs-body-bg: var(--salon-fondo);
        --bs-body-color: var(--salon-texto);
        --bs-border-color: var(--salon-borde);
        --bs-link-color: var(--salon-texto);

        /*
         * Bootstrap fija estos tokens en valores CLAROS y solo los invierte
         * cuando encuentra su propio `data-bs-theme="dark"`, que aquí no se usa
         * (el interruptor es `data-tema`). Sin reasignarlos, en oscuro quedaban
         * negros sobre negro: la pestaña activa de un nav-tabs, el texto de una
         * `.table`, `.text-body-emphasis` y el fondo de los tooltips.
         */
        --bs-emphasis-color:     var(--salon-texto);
        --bs-emphasis-color-rgb: 245, 245, 247;
        --bs-secondary-color:     var(--salon-texto-suave);
        --bs-secondary-color-rgb: 199, 199, 204;
        --bs-secondary-bg:        var(--salon-superficie-alta);
        --bs-secondary-bg-rgb:    31, 31, 34;
        --bs-tertiary-color:      var(--salon-texto-tenue);
        --bs-tertiary-color-rgb:  142, 142, 147;
        --bs-tertiary-bg:         var(--salon-superficie);
        --bs-tertiary-bg-rgb:     22, 22, 24;
    }
}

:root[data-tema="oscuro"] {
    --salon-fondo:            #0B0B0C;
    --salon-superficie:       #161618;
    --salon-superficie-alta:  #1F1F22;
    --salon-superficie-hover: #232326;
    --salon-texto:            #F5F5F7;
    --salon-texto-suave:      #C7C7CC;
    --salon-texto-tenue:      #8E8E93;
    --salon-borde:            #2C2C2E;
    --salon-borde-fuerte:     #3A3A3C;
    --salon-sobre-acento:     #111111;

    /* El champán en oscuro deja de ser crema y pasa a dorado apagado; si no,
       cualquier fondo de acento queda casi blanco bajo texto claro, que es
       justo lo que ocultaba los nombres de los profesionales en la agenda. */
    --salon-champagne:       #2A2517;
    --salon-champagne-2:     #3A3220;
    --salon-sobre-champagne: #E3D9A6;
    --salon-boton-solido:       #F5F5F7;
    --salon-boton-solido-hover: #DCDCE0;
    --salon-sobre-boton-solido: #0B0B0C;
    --salon-exito-suave: #12271F;
    --salon-aviso-suave: #2A2114;
    --salon-error-suave: #2A1614;
    --salon-info-suave:  #12212B;
    --salon-sombra-sm: 0 1px 2px rgba(0, 0, 0, .4);
    --salon-sombra:    0 2px 8px rgba(0, 0, 0, .45);
    --salon-sombra-md: 0 8px 24px rgba(0, 0, 0, .5);
    --salon-sombra-lg: 0 16px 48px rgba(0, 0, 0, .6);

    /* Estados de reserva en oscuro: se conserva el TONO de cada estado para no
       tener que reaprender el código de colores, pero el fondo se oscurece y el
       texto se aclara. Invertir la luminosidad sin invertir el tono es lo que
       permite que el verde siga leyéndose como verde sobre negro.            */
    --cita-pendiente-borde:  #D9A441;
    --cita-pendiente-fondo:  #2E2312;
    --cita-pendiente-texto:  #F0D9A8;

    --cita-reservada-borde:  #5E9BC0;
    --cita-reservada-fondo:  #12242F;
    --cita-reservada-texto:  #B9DCEF;

    --cita-confirmada-borde: #4FA97F;
    --cita-confirmada-fondo: #12281F;
    --cita-confirmada-texto: #A9E2C4;

    --cita-en_camino-borde:  #3AA6BF;
    --cita-en_camino-fondo:  #0F272E;
    --cita-en_camino-texto:  #A5DDEA;

    --cita-atendida-borde:   #9B7ED1;
    --cita-atendida-fondo:   #201A2E;
    --cita-atendida-texto:   #CFC0EC;

    --cita-finalizada-borde: #6E6E73;
    --cita-finalizada-fondo: #1E1E21;
    --cita-finalizada-texto: #B4B4B9;

    --cita-cancelada-borde:  #D4564D;
    --cita-cancelada-fondo:  #2C1614;
    --cita-cancelada-texto:  #F0B5B0;

    --cita-no_asistio-borde: #E2685C;
    --cita-no_asistio-fondo: #3A1512;
    --cita-no_asistio-texto: #F7C3BD;

    --cita-reagendada-borde: #8794A3;
    --cita-reagendada-fondo: #1D2126;
    --cita-reagendada-texto: #C3CCD6;

    --cita-bloqueo-borde:    #4A4A4E;
    --cita-bloqueo-fondo:    #1C1C1F;

    --bs-body-bg: var(--salon-fondo);
    --bs-body-color: var(--salon-texto);
    --bs-border-color: var(--salon-borde);
    --bs-link-color: var(--salon-texto);

    /* Mismos tokens que en el bloque de `prefers-color-scheme: dark`. Los dos
       han de ir siempre a la par: si solo se toca uno, el fallo reaparece para
       la mitad de los usuarios y no hay forma de verlo desde el navegador
       propio. */
    --bs-emphasis-color:     var(--salon-texto);
    --bs-emphasis-color-rgb: 245, 245, 247;
    --bs-secondary-color:     var(--salon-texto-suave);
    --bs-secondary-color-rgb: 199, 199, 204;
    --bs-secondary-bg:        var(--salon-superficie-alta);
    --bs-secondary-bg-rgb:    31, 31, 34;
    --bs-tertiary-color:      var(--salon-texto-tenue);
    --bs-tertiary-color-rgb:  142, 142, 147;
    --bs-tertiary-bg:         var(--salon-superficie);
    --bs-tertiary-bg-rgb:     22, 22, 24;
}

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

* { -webkit-tap-highlight-color: transparent; }

body {
    background-color: var(--salon-fondo);
    color: var(--salon-texto);
    font-family: var(--bs-body-font-family);
    font-size: .9375rem;
    line-height: 1.6;
    letter-spacing: -.01em;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
    font-weight: 600;
    letter-spacing: -.025em;
    color: var(--salon-texto);
}

h1, .h1 { font-size: 1.75rem; }
h2, .h2 { font-size: 1.4rem; }
h3, .h3 { font-size: 1.15rem; }

a { text-decoration: none; transition: color var(--salon-transicion); }

/* Accesibilidad (apartado 50): el foco SIEMPRE debe verse.
   Se usa :focus-visible para no molestar al usuario de ratón. */
:focus-visible {
    outline: 2px solid var(--salon-acento);
    outline-offset: 2px;
    border-radius: 4px;
}

/* Respeta a quien pidió menos movimiento en su sistema operativo. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        transition-duration: .001ms !important;
        scroll-behavior: auto !important;
    }
}

/* Texto solo para lectores de pantalla */
.solo-lectores {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Salto al contenido: primer elemento tabulable de cada pantalla */
.salto-contenido {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 2000;
    padding: .75rem 1.25rem;
    background: var(--salon-negro);
    color: #fff;
    border-radius: 0 0 var(--salon-radio) 0;
}
.salto-contenido:focus { left: 0; }

::selection { background: var(--salon-champagne-2); color: var(--salon-sobre-champagne); }

/* Barra de desplazamiento discreta */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--salon-gris-300);
    border-radius: 10px;
    border: 3px solid var(--salon-fondo);
}
::-webkit-scrollbar-thumb:hover { background: var(--salon-gris-400); }

/* =============================================================================
   ESTRUCTURA: barra lateral + barra superior
   ============================================================================= */

.salon-layout {
    display: flex;
    min-height: 100vh;
}

.salon-sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: var(--salon-sidebar-ancho);
    background: var(--salon-superficie);
    border-right: 1px solid var(--salon-borde);
    display: flex;
    flex-direction: column;
    z-index: 1040;
    transition: transform var(--salon-transicion-lenta);
}

.salon-sidebar__marca {
    height: var(--salon-topbar-alto);
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: 0 1.25rem;
    border-bottom: 1px solid var(--salon-borde);
    flex-shrink: 0;
}

/* Logotipo del centro en la barra lateral. La fila mide 64 px, así que 44
   aprovecha el espacio sin tocar los bordes; a 32 px un logotipo con detalle
   —que es casi cualquiera— no se distinguía de una mancha de color. */
.salon-sidebar__logo {
    width: 44px;
    height: 44px;
    border-radius: 10px;
    object-fit: contain;
    background: #fff;
    padding: 3px;
    flex: none;
}

.salon-sidebar__marca-texto {
    font-weight: 600;
    font-size: .95rem;
    letter-spacing: -.02em;
    line-height: 1.2;
    color: var(--salon-texto);
}

.salon-sidebar__marca-sub {
    display: block;
    font-size: .7rem;
    font-weight: 400;
    color: var(--salon-texto-tenue);
    letter-spacing: .04em;
    text-transform: uppercase;
}

.salon-sidebar__nav {
    flex: 1;
    overflow-y: auto;
    padding: 1rem .75rem 2rem;
}

.salon-sidebar__grupo {
    padding: 1.25rem .75rem .4rem;
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--salon-texto-tenue);
}
.salon-sidebar__grupo:first-child { padding-top: .25rem; }

.salon-sidebar__enlace {
    display: flex;
    align-items: center;
    gap: .8rem;
    padding: .6rem .75rem;
    margin-bottom: 2px;
    border-radius: var(--salon-radio-sm);
    color: var(--salon-texto-suave);
    font-size: .875rem;
    font-weight: 450;
    transition: background var(--salon-transicion), color var(--salon-transicion);
    position: relative;
}

.salon-sidebar__enlace i {
    width: 18px;
    text-align: center;
    font-size: .9rem;
    color: var(--salon-texto-tenue);
    transition: color var(--salon-transicion);
}

.salon-sidebar__enlace:hover {
    background: var(--salon-superficie-hover);
    color: var(--salon-texto);
}
.salon-sidebar__enlace:hover i { color: var(--salon-texto); }

.salon-sidebar__enlace.activo {
    background: var(--salon-negro);
    color: #fff;
    font-weight: 500;
}
.salon-sidebar__enlace.activo i { color: var(--salon-dorado); }

:root[data-tema="oscuro"] .salon-sidebar__enlace.activo,
.salon-sidebar__enlace.activo:where(:root[data-tema="oscuro"] *) {
    background: var(--salon-superficie-alta);
}

/*
 * Marca de «abre fuera del panel». Deliberadamente discreta: informa sin
 * competir con el icono del propio enlace, que es lo que el ojo busca.
 */
.salon-sidebar__enlace .salon-sidebar__externo,
.salon-sidebar__enlace:hover .salon-sidebar__externo {
    width: auto;
    margin-left: auto;
    font-size: .62rem;
    color: var(--salon-texto-tenue);
    opacity: .75;
}

.salon-sidebar__badge {
    margin-left: auto;
    font-size: .68rem;
    font-weight: 600;
    padding: .1rem .4rem;
    border-radius: 20px;
    background: var(--salon-error);
    color: #fff;
    min-width: 18px;
    text-align: center;
}

.salon-sidebar__pie {
    padding: .75rem;
    border-top: 1px solid var(--salon-borde);
    flex-shrink: 0;
}

.salon-principal {
    flex: 1;
    margin-left: var(--salon-sidebar-ancho);
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.salon-topbar {
    height: var(--salon-topbar-alto);
    background: color-mix(in srgb, var(--salon-superficie) 85%, transparent);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    border-bottom: 1px solid var(--salon-borde);
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0 1.5rem;
    position: sticky;
    top: 0;
    z-index: 1030;
}

.salon-topbar__titulo {
    font-size: 1.05rem;
    font-weight: 600;
    letter-spacing: -.02em;
    margin: 0;
}

.salon-topbar__acciones {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: .5rem;
}

.salon-contenido {
    flex: 1;
    padding: 1.75rem 1.5rem 3rem;
    max-width: 1600px;
    width: 100%;
}

.salon-pie {
    padding: 1rem 1.5rem;
    border-top: 1px solid var(--salon-borde);
    color: var(--salon-texto-tenue);
    font-size: .78rem;
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

/* Botón de menú móvil y velo */
.salon-menu-boton { display: none; }

.salon-velo {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .35);
    backdrop-filter: blur(2px);
    z-index: 1035;
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--salon-transicion), visibility var(--salon-transicion);
}
.salon-velo.visible { opacity: 1; visibility: visible; }

/* =============================================================================
   COMPONENTES
   ============================================================================= */

/* ── Tarjeta ─────────────────────────────────────────────────────────────── */
.salon-card {
    background: var(--salon-superficie);
    border: 1px solid var(--salon-borde);
    border-radius: var(--salon-radio-lg);
    box-shadow: var(--salon-sombra-sm);
    transition: box-shadow var(--salon-transicion), border-color var(--salon-transicion);
}

.salon-card--interactiva:hover {
    box-shadow: var(--salon-sombra-md);
    border-color: var(--salon-borde-fuerte);
}

.salon-card__cabecera {
    padding: 1.15rem 1.35rem;
    border-bottom: 1px solid var(--salon-borde);
    display: flex;
    align-items: center;
    gap: .75rem;
}

.salon-card__titulo {
    font-size: .95rem;
    font-weight: 600;
    margin: 0;
    letter-spacing: -.015em;
}

.salon-card__cuerpo { padding: 1.35rem; }

.salon-card__pie {
    padding: .9rem 1.35rem;
    border-top: 1px solid var(--salon-borde);
    background: var(--salon-gris-50);
    border-radius: 0 0 var(--salon-radio-lg) var(--salon-radio-lg);
}
:root[data-tema="oscuro"] .salon-card__pie { background: var(--salon-superficie-alta); }

/* ── Indicador (KPI) ─────────────────────────────────────────────────────── */
.salon-kpi {
    background: var(--salon-superficie);
    border: 1px solid var(--salon-borde);
    border-radius: var(--salon-radio-lg);
    padding: 1.25rem 1.35rem;
    height: 100%;
    transition: transform var(--salon-transicion), box-shadow var(--salon-transicion);
}

.salon-kpi:hover {
    transform: translateY(-2px);
    box-shadow: var(--salon-sombra-md);
}

/* Un KPI que además filtra la lista que tiene debajo.
   Es un <button> de verdad —no un div con onclick— para que se alcance con el
   tabulador y se anuncie como control. Solo reinicia el aspecto del botón: lo
   demás lo pone `.salon-kpi`, y el foco lo pone la regla global. */
.salon-kpi--accion {
    display: block;
    width: 100%;
    text-align: left;
    font: inherit;
    color: inherit;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}

.salon-kpi--accion[aria-pressed="true"] {
    border-color: var(--salon-acento);
}

.salon-kpi__etiqueta {
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--salon-texto-tenue);
    margin-bottom: .5rem;
    display: flex;
    align-items: center;
    gap: .45rem;
}

.salon-kpi__valor {
    font-size: 1.75rem;
    font-weight: 650;
    letter-spacing: -.03em;
    line-height: 1.1;
    color: var(--salon-texto);
    font-variant-numeric: tabular-nums;
}

.salon-kpi__pie {
    margin-top: .55rem;
    font-size: .78rem;
    color: var(--salon-texto-tenue);
    display: flex;
    align-items: center;
    gap: .35rem;
}

.salon-kpi__delta { font-weight: 600; }
.salon-kpi__delta--sube  { color: var(--salon-exito); }
.salon-kpi__delta--baja  { color: var(--salon-error); }

/* ── Botones ─────────────────────────────────────────────────────────────── */
.btn {
    font-size: .875rem;
    font-weight: 500;
    letter-spacing: -.01em;
    border-radius: var(--salon-radio-sm);
    padding: .5rem 1rem;
    transition: all var(--salon-transicion);
    border-width: 1px;
}

.btn:active { transform: scale(.985); }

.btn-primary,
.btn-dark {
    background: var(--salon-boton-solido);
    border-color: var(--salon-boton-solido);
    color: var(--salon-sobre-boton-solido);
}
.btn-primary:hover, .btn-dark:hover {
    background: var(--salon-boton-solido-hover);
    border-color: var(--salon-boton-solido-hover);
    color: var(--salon-sobre-boton-solido);
}

.btn-outline-secondary {
    border-color: var(--salon-borde-fuerte);
    color: var(--salon-texto-suave);
    background: var(--salon-superficie);
}
.btn-outline-secondary:hover {
    background: var(--salon-superficie-hover);
    border-color: var(--salon-gris-400);
    color: var(--salon-texto);
}

.btn-acento {
    background: var(--salon-dorado);
    border-color: var(--salon-dorado);
    color: var(--salon-sobre-acento);
    font-weight: 600;
}
.btn-acento:hover {
    background: #B89E2C;
    border-color: #B89E2C;
    color: var(--salon-sobre-acento);
}

.btn-icono {
    width: 36px;
    height: 36px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--salon-radio-sm);
    border: 1px solid transparent;
    background: transparent;
    color: var(--salon-texto-suave);
    transition: all var(--salon-transicion);
}
.btn-icono:hover {
    background: var(--salon-superficie-hover);
    color: var(--salon-texto);
}

/* ── Formularios ─────────────────────────────────────────────────────────── */
.form-label {
    font-size: .8125rem;
    font-weight: 500;
    color: var(--salon-texto-suave);
    margin-bottom: .35rem;
}

.form-label .obligatorio { color: var(--salon-error); margin-left: 2px; }

.form-control,
.form-select {
    background: var(--salon-superficie);
    border: 1px solid var(--salon-borde-fuerte);
    border-radius: var(--salon-radio-sm);
    color: var(--salon-texto);
    font-size: .9rem;
    padding: .55rem .8rem;
    transition: border-color var(--salon-transicion), box-shadow var(--salon-transicion);
}

.form-control:focus,
.form-select:focus {
    background: var(--salon-superficie);
    border-color: var(--salon-negro);
    box-shadow: 0 0 0 3px rgba(17, 17, 17, .07);
    color: var(--salon-texto);
}
:root[data-tema="oscuro"] .form-control:focus,
:root[data-tema="oscuro"] .form-select:focus {
    border-color: var(--salon-dorado);
    box-shadow: 0 0 0 3px rgba(201, 176, 55, .15);
}

.form-control::placeholder { color: var(--salon-texto-tenue); }

.form-control.is-invalid,
.form-select.is-invalid {
    border-color: var(--salon-error);
    background-image: none;
}
.invalid-feedback { font-size: .78rem; color: var(--salon-error); }

.form-text { font-size: .78rem; color: var(--salon-texto-tenue); }

.form-check-input:checked {
    background-color: var(--salon-negro);
    border-color: var(--salon-negro);
}
.form-switch .form-check-input:checked {
    background-color: var(--salon-exito);
    border-color: var(--salon-exito);
}

/* ── Tablas ──────────────────────────────────────────────────────────────── */
.salon-tabla-envoltorio {
    background: var(--salon-superficie);
    border: 1px solid var(--salon-borde);
    border-radius: var(--salon-radio-lg);
    overflow: hidden;
}

/* Las tablas anchas se desplazan dentro de su caja; la página nunca se
   desplaza horizontalmente. */
.salon-tabla-scroll { overflow-x: auto; }

.salon-tabla {
    width: 100%;
    margin: 0;
    font-size: .875rem;
    border-collapse: separate;
    border-spacing: 0;
}

.salon-tabla thead th {
    background: var(--salon-gris-50);
    border-bottom: 1px solid var(--salon-borde);
    padding: .7rem 1rem;
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--salon-texto-tenue);
    white-space: nowrap;
    position: sticky;
    top: 0;
    z-index: 1;
}
:root[data-tema="oscuro"] .salon-tabla thead th { background: var(--salon-superficie-alta); }

.salon-tabla tbody td {
    padding: .8rem 1rem;
    border-bottom: 1px solid var(--salon-borde);
    color: var(--salon-texto);
    vertical-align: middle;
}

.salon-tabla tbody tr:last-child td { border-bottom: 0; }

.salon-tabla tbody tr { transition: background var(--salon-transicion); }
.salon-tabla tbody tr:hover { background: var(--salon-superficie-hover); }

.salon-tabla .numero { text-align: right; font-variant-numeric: tabular-nums; }

.salon-tabla__orden {
    cursor: pointer;
    user-select: none;
}
.salon-tabla__orden::after {
    content: "\f0dc";
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    margin-left: .4rem;
    opacity: .3;
    font-size: .7em;
}
.salon-tabla__orden[data-direccion="asc"]::after  { content: "\f0de"; opacity: 1; }
.salon-tabla__orden[data-direccion="desc"]::after { content: "\f0dd"; opacity: 1; }

/* ── Distintivos de estado ───────────────────────────────────────────────── */
.salon-badge {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .01em;
    padding: .22rem .6rem;
    border-radius: 20px;
    border: 1px solid transparent;
    white-space: nowrap;
}

.salon-badge i { font-size: .85em; }

.salon-badge--exito     { background: var(--salon-exito-suave); color: var(--salon-exito); }
.salon-badge--aviso     { background: var(--salon-aviso-suave); color: var(--salon-aviso); }
.salon-badge--error,
.salon-badge--danger    { background: var(--salon-error-suave); color: var(--salon-error); }
.salon-badge--info      { background: var(--salon-info-suave);  color: var(--salon-info); }
.salon-badge--primary   { background: var(--salon-info-suave);  color: var(--salon-info); }
.salon-badge--warning   { background: var(--salon-aviso-suave); color: var(--salon-aviso); }
.salon-badge--success   { background: var(--salon-exito-suave); color: var(--salon-exito); }
.salon-badge--secondary { background: var(--salon-gris-100);    color: var(--salon-gris-700); }
.salon-badge--dark      { background: var(--salon-negro);       color: #fff; }
.salon-badge--acento    { background: var(--salon-champagne);   color: var(--salon-sobre-champagne); }

/* Distintivo de estado de reserva: toma su color del mismo juego de variables
   que el calendario, en vez de las clases genéricas de Bootstrap. Con aquéllas
   «atendida» y «finalizada» compartían el verde de `success`, y el distintivo
   contradecía al bloque del calendario que sí las distinguía. Basta con poner
   `data-estado-cita` en el elemento para que el color salga solo.           */
.salon-badge--cita {
    background: var(--cita-fondo, var(--salon-gris-100));
    color: var(--cita-texto, var(--salon-gris-700));
    border-color: transparent;   /* respaldo si no hay color-mix() */
    border-color: color-mix(in srgb, var(--cita-borde, var(--salon-gris-500)) 30%, transparent);
}
:root[data-tema="oscuro"] .salon-badge--secondary { background: var(--salon-superficie-alta); color: var(--salon-texto-suave); }

/* Fila o bloque resaltado con el color de acento: notificación sin leer,
   registro destacado, etc. Existe como clase para que ningún JavaScript vuelva
   a escribir el champán en un atributo `style`, que es como el texto terminaba
   siendo ilegible en tema oscuro: el fondo se fijaba y el color no. */
.salon-fila-destacada {
    background: var(--salon-champagne);
    color: var(--salon-sobre-champagne);
}

/* ── Avatar ──────────────────────────────────────────────────────────────── */
.salon-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--salon-champagne);
    color: var(--salon-sobre-champagne);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: .78rem;
    font-weight: 650;
    letter-spacing: .02em;
    flex-shrink: 0;
    overflow: hidden;
    border: 1px solid var(--salon-borde);
}
.salon-avatar img { width: 100%; height: 100%; object-fit: cover; }
.salon-avatar--sm { width: 28px; height: 28px; font-size: .68rem; }
.salon-avatar--lg { width: 56px; height: 56px; font-size: 1.1rem; }

/* ── Estado vacío ────────────────────────────────────────────────────────── */
.salon-vacio {
    text-align: center;
    padding: 3.5rem 1.5rem;
    color: var(--salon-texto-tenue);
}
.salon-vacio i {
    font-size: 2.25rem;
    opacity: .25;
    margin-bottom: .9rem;
    display: block;
}
.salon-vacio__titulo {
    font-weight: 600;
    color: var(--salon-texto-suave);
    margin-bottom: .3rem;
}
.salon-vacio__texto { font-size: .875rem; max-width: 380px; margin: 0 auto; }

/* ── Avisos / alertas ────────────────────────────────────────────────────── */
.salon-aviso {
    display: flex;
    gap: .8rem;
    padding: .9rem 1.1rem;
    border-radius: var(--salon-radio);
    border: 1px solid transparent;
    font-size: .875rem;
    align-items: flex-start;
}
.salon-aviso i { margin-top: .15rem; flex-shrink: 0; }
.salon-aviso--exito { background: var(--salon-exito-suave); border-color: color-mix(in srgb, var(--salon-exito) 25%, transparent); color: var(--salon-exito); }
.salon-aviso--error { background: var(--salon-error-suave); border-color: color-mix(in srgb, var(--salon-error) 25%, transparent); color: var(--salon-error); }
.salon-aviso--aviso { background: var(--salon-aviso-suave); border-color: color-mix(in srgb, var(--salon-aviso) 25%, transparent); color: var(--salon-aviso); }
.salon-aviso--info  { background: var(--salon-info-suave);  border-color: color-mix(in srgb, var(--salon-info) 25%, transparent);  color: var(--salon-info); }

/* ── Notificaciones emergentes ───────────────────────────────────────────── */
.salon-toasts {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 1090;
    display: flex;
    flex-direction: column;
    gap: .6rem;
    max-width: min(380px, calc(100vw - 2rem));
}

.salon-toast {
    background: var(--salon-superficie);
    border: 1px solid var(--salon-borde);
    border-left: 3px solid var(--salon-texto-tenue);
    border-radius: var(--salon-radio);
    box-shadow: var(--salon-sombra-lg);
    padding: .85rem 1rem;
    display: flex;
    align-items: flex-start;
    gap: .7rem;
    font-size: .875rem;
    animation: salon-entrada var(--salon-transicion-lenta) both;
}

.salon-toast--exito { border-left-color: var(--salon-exito); }
.salon-toast--error { border-left-color: var(--salon-error); }
.salon-toast--aviso { border-left-color: var(--salon-aviso); }
.salon-toast--info  { border-left-color: var(--salon-info); }

.salon-toast__icono { flex-shrink: 0; margin-top: .1rem; }
.salon-toast--exito .salon-toast__icono { color: var(--salon-exito); }
.salon-toast--error .salon-toast__icono { color: var(--salon-error); }
.salon-toast--aviso .salon-toast__icono { color: var(--salon-aviso); }
.salon-toast--info  .salon-toast__icono { color: var(--salon-info); }

.salon-toast__cuerpo { flex: 1; min-width: 0; }
.salon-toast__cerrar {
    background: none; border: 0; color: var(--salon-texto-tenue);
    padding: 0; line-height: 1; cursor: pointer;
}

.salon-toast.saliendo { animation: salon-salida var(--salon-transicion) both; }

@keyframes salon-entrada {
    from { opacity: 0; transform: translateX(16px) scale(.98); }
    to   { opacity: 1; transform: translateX(0) scale(1); }
}
@keyframes salon-salida {
    to { opacity: 0; transform: translateX(16px) scale(.98); }
}

/* ── Pestañas ────────────────────────────────────────────────────────────── */
/*
 * Corregidos los tokens de Bootstrap, la pestaña activa ya se lee. Faltaba lo
 * otro: `--bs-nav-link-color` hereda de `--bs-link-color`, que en oscuro vale
 * el mismo blanco que el texto activo, así que activa e inactiva quedaban del
 * mismo color y solo las separaba el recuadro. Aquí se apagan las inactivas.
 */
.nav-tabs {
    /* `--salon-texto-suave`, no `--salon-texto-tenue`: el tenue deja las
       pestañas inactivas en 3,1:1 sobre el fondo claro, por debajo del mínimo
       legible. Este da 8,7:1 en claro y 11,7:1 en oscuro. */
    --bs-nav-link-color:                   var(--salon-texto-suave);
    --bs-nav-link-hover-color:             var(--salon-texto);
    --bs-nav-tabs-border-color:            var(--salon-borde);
    --bs-nav-tabs-link-active-color:       var(--salon-texto);
    --bs-nav-tabs-link-active-bg:          var(--salon-fondo);
    --bs-nav-tabs-link-active-border-color: var(--salon-borde) var(--salon-borde) var(--salon-fondo);
    /* Al pasar el ratón solo se insinúa el borde inferior: el recuadro completo
       de Bootstrap parece que la pestaña ya está seleccionada. */
    --bs-nav-tabs-link-hover-border-color:  transparent transparent var(--salon-borde-fuerte);
}

.nav-tabs .nav-link.active { font-weight: 600; }

/*
 * Dentro de un modal el fondo no es el de la página, sino el de la tarjeta. Sin
 * esto la pestaña activa se recorta con un rectángulo del color equivocado (le
 * pasa a las pestañas de la ficha de producto).
 */
.modal .nav-tabs {
    --bs-nav-tabs-link-active-bg: var(--salon-superficie);
    --bs-nav-tabs-link-active-border-color:
        var(--salon-borde) var(--salon-borde) var(--salon-superficie);
}

/* ── Modales ─────────────────────────────────────────────────────────────── */
.modal-content {
    background: var(--salon-superficie);
    border: 1px solid var(--salon-borde);
    border-radius: var(--salon-radio-xl);
    box-shadow: var(--salon-sombra-lg);
}
.modal-header {
    border-bottom: 1px solid var(--salon-borde);
    padding: 1.15rem 1.5rem;
}
.modal-title { font-size: 1.05rem; font-weight: 600; letter-spacing: -.02em; }
.modal-body { padding: 1.5rem; }
.modal-footer { border-top: 1px solid var(--salon-borde); padding: 1rem 1.5rem; }
.modal-backdrop.show { opacity: .3; }

/* ── Menú desplegable ────────────────────────────────────────────────────── */
.dropdown-menu {
    background: var(--salon-superficie);
    border: 1px solid var(--salon-borde);
    border-radius: var(--salon-radio);
    box-shadow: var(--salon-sombra-md);
    padding: .35rem;
    font-size: .875rem;
    min-width: 200px;
}
.dropdown-item {
    border-radius: var(--salon-radio-sm);
    padding: .5rem .7rem;
    color: var(--salon-texto-suave);
    display: flex;
    align-items: center;
    gap: .6rem;
}
.dropdown-item:hover, .dropdown-item:focus {
    background: var(--salon-superficie-hover);
    color: var(--salon-texto);
}
.dropdown-item i { width: 16px; text-align: center; color: var(--salon-texto-tenue); }
.dropdown-divider { border-color: var(--salon-borde); margin: .35rem 0; }
.dropdown-header {
    font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
    color: var(--salon-texto-tenue); font-weight: 600; padding: .5rem .7rem .25rem;
}

/* ── Cargando ────────────────────────────────────────────────────────────── */
.salon-cargando {
    display: inline-block;
    width: 16px; height: 16px;
    border: 2px solid var(--salon-borde-fuerte);
    border-top-color: var(--salon-texto);
    border-radius: 50%;
    animation: salon-girar .7s linear infinite;
}
@keyframes salon-girar { to { transform: rotate(360deg); } }

.salon-esqueleto {
    background: linear-gradient(90deg, var(--salon-gris-100) 25%, var(--salon-gris-200) 50%, var(--salon-gris-100) 75%);
    background-size: 200% 100%;
    animation: salon-brillo 1.4s ease-in-out infinite;
    border-radius: var(--salon-radio-sm);
    height: 1rem;
}
@keyframes salon-brillo {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* ── Paginación ──────────────────────────────────────────────────────────── */
.salon-paginacion {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .85rem 1.25rem;
    border-top: 1px solid var(--salon-borde);
    font-size: .8125rem;
    color: var(--salon-texto-tenue);
    flex-wrap: wrap;
}
.salon-paginacion__botones { display: flex; gap: .3rem; }
.salon-paginacion__boton {
    min-width: 32px; height: 32px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--salon-borde);
    background: var(--salon-superficie);
    border-radius: var(--salon-radio-sm);
    color: var(--salon-texto-suave);
    font-size: .8125rem;
    cursor: pointer;
    transition: all var(--salon-transicion);
    padding: 0 .5rem;
}
.salon-paginacion__boton:hover:not(:disabled) { background: var(--salon-superficie-hover); }
.salon-paginacion__boton.activo { background: var(--salon-boton-solido); border-color: var(--salon-boton-solido); color: var(--salon-sobre-boton-solido); }
.salon-paginacion__boton:disabled { opacity: .4; cursor: not-allowed; }

/* =============================================================================
   PANTALLA DE ACCESO
   ============================================================================= */

.salon-login {
    min-height: 100vh;
    display: grid;
    grid-template-columns: 1fr 1fr;
    background: var(--salon-superficie);
}

.salon-login__lateral {
    background:
        radial-gradient(1200px 600px at 20% 10%, rgba(201, 176, 55, .10), transparent 60%),
        linear-gradient(160deg, #16161A 0%, #0B0B0C 100%);
    color: #fff;
    padding: 3.5rem;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    position: relative;
    overflow: hidden;
}

.salon-login__lateral::after {
    content: "";
    position: absolute;
    width: 460px; height: 460px;
    right: -180px; bottom: -180px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, .06);
}

.salon-login__marca {
    display: flex; align-items: center; gap: .8rem;
    font-size: 1rem; font-weight: 600; letter-spacing: -.02em;
    position: relative;
}

/* Logotipo del centro en el lateral. Fondo claro y `object-fit: contain`: la
   mayoría de los logotipos vienen sobre blanco, y recortarlos o dejarlos flotar
   sobre el degradado oscuro los estropea. */
.salon-login__logo {
    width: 56px;
    height: 56px;
    border-radius: 12px;
    object-fit: contain;
    background: #fff;
    padding: 3px;
    flex: none;
}

/* Marca del formulario: solo se ve cuando el lateral se oculta, en móvil. */
.salon-login__marca-movil { display: none; }

.salon-login__lema {
    font-size: 2.1rem;
    font-weight: 300;
    line-height: 1.25;
    letter-spacing: -.035em;
    max-width: 460px;
    position: relative;
}
.salon-login__lema strong { font-weight: 600; color: var(--salon-dorado-claro); }

.salon-login__pie { font-size: .8rem; color: rgba(255, 255, 255, .45); position: relative; }

.salon-login__panel {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2.5rem;
}

.salon-login__caja { width: 100%; max-width: 380px; }

.salon-login__titulo {
    font-size: 1.6rem;
    font-weight: 600;
    letter-spacing: -.03em;
    margin-bottom: .35rem;
}
.salon-login__subtitulo {
    color: var(--salon-texto-tenue);
    font-size: .9rem;
    margin-bottom: 2rem;
}

.salon-campo-password { position: relative; }
.salon-campo-password .form-control { padding-right: 2.75rem; }
.salon-ver-password {
    position: absolute;
    right: .35rem; top: 50%;
    transform: translateY(-50%);
    width: 32px; height: 32px;
    border: 0; background: none;
    color: var(--salon-texto-tenue);
    border-radius: var(--salon-radio-sm);
    cursor: pointer;
}
.salon-ver-password:hover { color: var(--salon-texto); background: var(--salon-superficie-hover); }

/* =============================================================================
   RESPONSIVO
   Apartado 3: la experiencia móvil es prioritaria porque la mayoría de las
   reservas llegarán desde el teléfono.
   ============================================================================= */

@media (max-width: 991.98px) {
    .salon-sidebar { transform: translateX(-100%); box-shadow: var(--salon-sombra-lg); }
    .salon-sidebar.abierta { transform: translateX(0); }
    .salon-principal { margin-left: 0; }
    .salon-menu-boton { display: inline-flex; }
    .salon-contenido { padding: 1.25rem 1rem 2.5rem; }
    .salon-login { grid-template-columns: 1fr; }
    .salon-login__lateral { display: none; }

    /* Sin el lateral, la marca pasa al formulario: si no, la pantalla de acceso
       en un teléfono no dice de qué centro es. */
    .salon-login__marca-movil {
        display: flex;
        align-items: center;
        gap: .7rem;
        margin-bottom: 1.6rem;
        font-size: 1.05rem;
        font-weight: 600;
        letter-spacing: -.02em;
    }

    .salon-login__marca-movil img {
        width: 64px;
        height: 64px;
        border-radius: 14px;
        object-fit: contain;
        background: #fff;
        padding: 3px;
        border: 1px solid var(--salon-borde);
        flex: none;
    }
}

@media (max-width: 575.98px) {
    :root { --salon-topbar-alto: 56px; }

    .salon-topbar { padding: 0 .9rem; }
    .salon-topbar__titulo { font-size: .95rem; }
    .salon-contenido { padding: 1rem .75rem 2.5rem; }
    .salon-card__cuerpo { padding: 1rem; }
    .salon-kpi { padding: 1rem; }
    .salon-kpi__valor { font-size: 1.45rem; }
    .salon-toasts { top: auto; bottom: 1rem; left: .75rem; right: .75rem; max-width: none; }

    /* Los objetivos táctiles deben poder pulsarse con el pulgar (WCAG 2.5.5) */
    .btn, .form-control, .form-select { min-height: 44px; }
    .btn-icono { width: 44px; height: 44px; }

    /* ── La barra superior en un teléfono ──────────────────────────────────
       Cuatro botones de icono son 176 px de los 360 que hay, y encima cada
       módulo añade los suyos CON texto: «Nueva reserva», «Bloquear». Todo
       junto no cabe, y lo que sobra ensancha la página entera.

       Se recorta lo que se puede recortar sin perder nada:
        · Los botones del módulo se quedan en su icono. Se comprobó que los
          treinta y uno lo llevan, así que ninguno queda irreconocible.
        · El interruptor de tema se va al menú del usuario: de las cuatro
          acciones de la barra es la que menos se pulsa.
        · Los huecos se estrechan.

       Lo que NO se toca son los 44 px del objetivo táctil. Estrecharlos habría
       sido la solución fácil y habría cambiado un desbordamiento por botones
       que se fallan con el pulgar. */

    .salon-topbar { gap: .5rem; }
    .salon-topbar__acciones { gap: .25rem; }

    /* El texto de estos botones es un nodo suelto, y a un nodo de texto no se
       le puede aplicar una regla. `font-size: 0` lo colapsa y el icono
       recupera el suyo. */
    .salon-topbar__acciones .btn {
        font-size: 0;
        padding-left: .55rem;
        padding-right: .55rem;
    }

    .salon-topbar__acciones .btn > i { font-size: .95rem; }
    .salon-topbar__acciones .btn > i.me-1 { margin-right: 0 !important; }

    /* Vive en el menú del usuario. */
    .salon-topbar > .salon-topbar__acciones > [data-accion="tema"] { display: none; }

    /* En pantallas estrechas la tabla se convierte en fichas apiladas */
    .salon-tabla--apilable thead { display: none; }
    .salon-tabla--apilable tbody tr {
        display: block;
        border: 1px solid var(--salon-borde);
        border-radius: var(--salon-radio);
        margin-bottom: .6rem;
        padding: .3rem 0;
    }
    .salon-tabla--apilable tbody td {
        display: flex;
        justify-content: space-between;
        gap: 1rem;
        border-bottom: 0;
        padding: .45rem .9rem;
        text-align: right;
    }
    .salon-tabla--apilable tbody td::before {
        content: attr(data-etiqueta);
        font-size: .72rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: .05em;
        color: var(--salon-texto-tenue);
        text-align: left;
    }
}

/* =============================================================================
   IMPRESIÓN (comprobantes, arqueos, reportes)
   ============================================================================= */

@media print {
    .salon-sidebar, .salon-topbar, .salon-pie, .salon-toasts,
    .no-imprimir, .btn { display: none !important; }
    .salon-principal { margin-left: 0; }
    .salon-contenido { padding: 0; }
    .salon-card { border: 0; box-shadow: none; }
    body { background: #fff; color: #000; font-size: 11pt; }
}

/* Utilidades propias */

/* Un hijo de flex nace con `min-width: auto`, así que se niega a encoger por
   debajo de su contenido. Eso hace que `text-truncate` no actúe nunca —el
   elemento siempre mide lo que mide su texto— y que lo que hay al lado acabe
   empujado fuera de la pantalla.

   Se usa en veintiún archivos dando por hecho que Bootstrap la traía. NO la
   trae: `min-w-*` no existe entre sus utilidades. Mientras faltó, la barra
   superior se desbordaba en cualquier teléfono en cuanto el título o el
   subtítulo eran largos. */
.min-w-0 { min-width: 0 !important; }

.texto-tenue   { color: var(--salon-texto-tenue) !important; }
.texto-suave   { color: var(--salon-texto-suave) !important; }
.texto-acento  { color: var(--salon-dorado) !important; }

/* Las tres de estado. Faltaban `texto-exito` y `texto-aviso`, que se usaban en
   el punto de venta y en la caja: sin ellas el importe cobrado y el aviso de
   diferencia salían del color del texto normal, que es justo lo que no se
   quería. Se añade `texto-error` por simetría, para no repetir la historia. */
.texto-exito   { color: var(--salon-exito) !important; }
.texto-aviso   { color: var(--salon-aviso) !important; }
.texto-error   { color: var(--salon-error) !important; }

/* ── Buscador con lupa dentro ─────────────────────────────────────────────
   Quince pantallas lo usan —listados de clientes, productos, reseñas…— y no
   estaba definido: la lupa caía ENCIMA del campo en vez de dentro, empujándolo
   una línea hacia abajo. La lupa no recibe el ratón para que pulsar sobre ella
   ponga el foco en el campo, que es lo que espera cualquiera. */
.salon-buscador { position: relative; }

.salon-buscador > i {
    position: absolute;
    left: .75rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: .875rem;
    color: var(--salon-texto-tenue);
    pointer-events: none;
}

.salon-buscador .form-control { padding-left: 2.25rem; }
.numero-tabular { font-variant-numeric: tabular-nums; }
.borde-suave   { border: 1px solid var(--salon-borde) !important; }
.fondo-superficie { background: var(--salon-superficie) !important; }

/* ── Buscador de clientes (compartido por agenda y datos personales) ──────── */
.buscador-cliente { position: relative; }

.buscador-cliente__resultados {
    position: absolute;
    top: 100%; left: 0; right: 0;
    z-index: 30;
    background: var(--salon-superficie);
    border: 1px solid var(--salon-borde);
    border-radius: var(--salon-radio);
    box-shadow: var(--salon-sombra-md);
    max-height: 260px;
    overflow-y: auto;
    margin-top: .25rem;
}

.buscador-cliente__item {
    /* Un <button> no hereda el color: sin esto queda negro en tema oscuro. */
    color: var(--salon-texto);
    display: flex; align-items: center; gap: .6rem;
    padding: .5rem .7rem;
    cursor: pointer; border: 0; background: none;
    width: 100%; text-align: left; font-size: .85rem;
}

.buscador-cliente__item:hover,
.buscador-cliente__item:focus { background: var(--salon-superficie-hover); }

/* ── Biblioteca de imágenes de correo ────────────────────────────────────────
   Rejilla de miniaturas del selector compartido (`imagenes-correo.js`). Vive en
   tema.css y no en un módulo porque la usan marketing y configuración. */

.img-rejilla {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: .8rem;
}

.img-ficha {
    position: relative;
    margin: 0;
    border: 1px solid var(--salon-borde);
    border-radius: var(--salon-radio);
    overflow: hidden;
    background: var(--salon-superficie);
}

.img-ficha__elegir {
    /* Un <button> no hereda el color: sin esto queda negro en tema oscuro. */
    color: var(--salon-texto);
    display: block;
    width: 100%;
    padding: 0;
    border: none;
    background: var(--salon-gris-100);
    cursor: pointer;
}

/* Alto fijo y `contain`: las imágenes de correo vienen en proporciones muy
   distintas, y recortarlas escondería justo la parte que se quiere ver. */
.img-ficha__elegir img {
    display: block;
    width: 100%;
    height: 110px;
    object-fit: contain;
}

.img-ficha__elegir:hover { background: var(--salon-superficie-hover); }

.img-ficha__elegir:focus-visible {
    outline: 2px solid var(--salon-acento);
    outline-offset: -2px;
}

.img-ficha__pie {
    display: flex;
    flex-direction: column;
    gap: .1rem;
    padding: .5rem .6rem;
    font-size: .78rem;
    border-top: 1px solid var(--salon-borde);
}

.img-ficha__nombre {
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.img-ficha__quitar {
    position: absolute;
    top: .35rem;
    right: .35rem;
    width: 28px;
    height: 28px;
    border: none;
    border-radius: 50%;
    background: rgba(0, 0, 0, .55);
    color: #fff;
    font-size: .75rem;
    cursor: pointer;
    opacity: 0;
    transition: opacity var(--salon-transicion);
}

.img-ficha:hover .img-ficha__quitar,
.img-ficha__quitar:focus-visible { opacity: 1; }

/* ── Imagen elegida en un ajuste ─────────────────────────────────────────── */

.img-elegida {
    display: flex;
    align-items: center;
    gap: .8rem;
    padding: .6rem;
    border: 1px solid var(--salon-borde);
    border-radius: var(--salon-radio-sm);
    background: var(--salon-superficie);
}

.img-elegida img {
    width: 84px;
    height: 56px;
    object-fit: contain;
    background: var(--salon-gris-100);
    border-radius: var(--salon-radio-sm);
    flex: none;
}

/* =============================================================================
   AYUDA EN PANTALLA
   -----------------------------------------------------------------------------
   El diálogo que explica qué hace cada pantalla. Lo pinta `footer.php` a partir
   de `funciones/ayuda.php`.

   Se busca densidad legible: son textos de varias líneas y una lista con el
   interlineado por omisión de Bootstrap se lee como un muro.
   ============================================================================= */

.ayuda-resumen {
    font-size: .95rem;
    line-height: 1.6;
    color: var(--salon-texto-suave);
    padding-bottom: .9rem;
    margin-bottom: 0;
    border-bottom: 1px solid var(--salon-borde);
}

.ayuda-seccion {
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--salon-texto-tenue);
    margin: 1.4rem 0 .5rem;
}

.ayuda-lista {
    margin: 0;
    padding-left: 1.15rem;
    font-size: .9rem;
    line-height: 1.6;
}

.ayuda-lista li + li { margin-top: .45rem; }

.ayuda-lista strong { color: var(--salon-texto); }

/* «Conviene saber»: lo que sorprende. Va destacado porque es la parte que de
   verdad responde las preguntas que se hacen. */
.ayuda-ojo {
    margin-top: 1.5rem;
    padding: .9rem 1rem;
    border-radius: var(--salon-radio);
    border: 1px solid var(--salon-borde);
    border-left: 3px solid var(--salon-acento);
    background: var(--salon-superficie-hover);
}

/* =============================================================================
   DIÁLOGO DE CONFIRMACIÓN
   -----------------------------------------------------------------------------
   Capa propia, no un modal de Bootstrap. La mitad de las confirmaciones del
   sistema se piden desde DENTRO de otro diálogo abierto —eliminar una ausencia
   desde la ficha del profesional, emitir un lote desde su formulario— y
   Bootstrap no apila modales: el segundo llega al mismo nivel, su fondo queda
   por encima del primero y se come los clics. La pantalla se ve pero no
   responde.

   Con capa propia no hay nada que apilar: se pone por encima de todo y de nadie
   depende. El z-index está muy por encima de los 1055 de Bootstrap a propósito,
   para que ningún componente futuro se cuele en medio.
   ============================================================================= */

.salon-confirmar {
    position: fixed;
    inset: 0;
    z-index: 20000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(0, 0, 0, .45);
    opacity: 0;
    transition: opacity .12s ease;
}

.salon-confirmar--visible { opacity: 1; }

.salon-confirmar__caja {
    width: 100%;
    max-width: 25rem;
    padding: 1.6rem 1.4rem 1.2rem;
    border-radius: var(--salon-radio-lg);
    background: var(--salon-superficie);
    border: 1px solid var(--salon-borde);
    box-shadow: 0 12px 40px rgba(0, 0, 0, .3);
    text-align: center;
    transform: translateY(6px);
    transition: transform .12s ease;
}

.salon-confirmar--visible .salon-confirmar__caja { transform: none; }

.salon-confirmar__icono { font-size: 2rem; margin-bottom: .8rem; line-height: 1; }

.salon-confirmar__titulo {
    font-size: 1.05rem;
    font-weight: 600;
    margin: 0 0 .5rem;
}

.salon-confirmar__texto {
    color: var(--salon-texto-suave);
    font-size: .9rem;
    line-height: 1.55;
    margin: 0 0 1.2rem;
    /* El mensaje a veces trae una lista de citas con saltos de línea. */
    white-space: pre-line;
    overflow-wrap: anywhere;
    max-height: 40vh;
    overflow-y: auto;
    text-align: left;
}

.salon-confirmar__acciones { display: flex; gap: .6rem; }

/* Variante con campo: `Salon.pedir()`. Alineada a la izquierda porque un
   formulario centrado se lee mal — la etiqueta y su campo tienen que empezar
   en el mismo sitio. */
.salon-confirmar__caja--form { text-align: left; }

.salon-pedir__campo { margin-bottom: 1.1rem; }
.salon-pedir__campo .form-label { font-size: .85rem; font-weight: 500; margin-bottom: .3rem; }
.salon-pedir__campo .invalid-feedback:empty { display: none; }

@media (prefers-reduced-motion: reduce) {
    .salon-confirmar,
    .salon-confirmar__caja { transition: none; }
}

/* =============================================================================
   BOTÓN DE CERRAR EN TEMA OSCURO
   -----------------------------------------------------------------------------
   Bootstrap dibuja la «X» de `.btn-close` con un SVG NEGRO incrustado en la
   propia hoja de estilos, no con un color heredable. Sobre la cabecera oscura
   de un diálogo queda negro sobre casi negro: el botón está ahí, ocupa su sitio
   y responde al clic, pero no se ve.

   La clase `btn-close-white` de Bootstrap resuelve esto, pero habría que
   añadirla a mano en los 31 sitios donde aparece el botón — y bastaría olvidar
   uno para dejar un diálogo del que no se sabe salir. Se invierte aquí, una vez
   y para todos.

   Se cubren las dos formas de activar el tema: la preferencia del sistema y el
   interruptor de la barra superior.
   ============================================================================= */

@media (prefers-color-scheme: dark) {
    :root:not([data-tema="claro"]) .btn-close {
        filter: invert(1) grayscale(100%) brightness(200%);
    }
}

:root[data-tema="oscuro"] .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}

/* =============================================================================
   VISTA PREVIA DE UNA GIFT CARD
   -----------------------------------------------------------------------------
   La tarjeta tal como se va a imprimir y como se ve en el correo. Se enseña
   antes de gastar una hoja y antes de que salga el mensaje.

   La proporción es la de una tarjeta de crédito (85,6 × 54 mm ≈ 1,585). Se fija
   con `aspect-ratio` y no con un alto en píxeles para que se comporte igual en
   un teléfono y en el escritorio: lo que importa es la forma, no el tamaño.

   Los colores van fijos y no con las variables del tema: la tarjeta es un objeto
   impreso, y en modo oscuro tiene que seguir viéndose como el papel que sale de
   la impresora, no como parte de la interfaz.
   ============================================================================= */

.gc-vista {
    position: relative;
    aspect-ratio: 85.6 / 54;
    width: 100%;
    max-width: 24rem;
    margin: 0 auto;
    border-radius: 12px;
    overflow: hidden;
    color: #fff;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: .9rem;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .28);
}

/* Velo oscuro sobre la imagen de fondo: sin él, un diseño claro deja el texto
   blanco ilegible, que es la mitad de los diseños que sube un centro. */
.gc-vista::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(0,0,0,.15) 0%, rgba(0,0,0,.55) 100%);
}

.gc-vista > * { position: relative; }

.gc-vista__centro {
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    text-shadow: 0 1px 3px rgba(0,0,0,.6);
}

.gc-vista__para { font-size: .78rem; opacity: .9; margin-top: -.4rem; }

/* Banda del pie: el código va sobre fondo claro porque es el único dato que
   hay que poder leer sí o sí, y una imagen de fondo puede tener cualquier cosa
   justo ahí. */
.gc-vista__banda {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: .6rem;
    background: rgba(255, 255, 255, .93);
    color: #111;
    border-radius: 8px;
    padding: .45rem .6rem;
}

.gc-vista__etiqueta {
    display: block;
    font-size: .58rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: #666;
}

.gc-vista__codigo {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .95rem;
    font-weight: 700;
    letter-spacing: .08em;
}

.gc-vista__monto    { font-size: 1.05rem; font-weight: 700; }
.gc-vista__concepto { font-size: .72rem; font-weight: 600; line-height: 1.2; max-width: 11rem; }
.gc-vista__vence    { font-size: .58rem; color: #666; margin-top: .1rem; }
