/* ARION Corporativo — overrides de marca sobre el tema base de panel base.
   Paleta y tipografías tomadas de docs/identidad/Manual de Identidad - ARION Corporativo.pdf */

/* Inter ya viene autohospedada en app.min.css (fuente del tema base); solo Syne hace falta desde Google Fonts */
@import url('https://fonts.googleapis.com/css2?family=Syne:wght@600;700;800&display=swap');

/* Piezas de ajedrez: cada imagen existe en versión clara y oscura y el tema
   del <html> (data-bs-theme) decide cuál se ve, al instante y sin recargar.
   Vive AQUÍ (custom.min.css, que layouts/panel.blade.php carga en TODA
   página) y no en resources/css/app.css (Vite): ese archivo solo llega a
   las pantallas que hacen @vite(['resources/css/app.css', ...]) en su
   @section('scripts'), y el dashboard/hub (100% Blade, sin Vue) no lo
   hacen — con la regla solo ahí, las dos piezas (clara y oscura) se veían
   superpuestas a la vez en tema oscuro, sin importar el tema. */
html[data-bs-theme="dark"] .pieza--claro,
html:not([data-bs-theme="dark"]) .pieza--oscuro { display: none !important; }

:root {
    /* Paleta de marca */
    --arion-cerulean: #007295;
    --arion-prussian-blue: #003347;
    --arion-indigo-dye: #20486B;
    --arion-timberwolf: #CCCDC5;
    --arion-raisin-black: #272727;

    --vz-font-family: 'Inter', sans-serif !important;
    --vz-body-font-family: 'Inter', sans-serif !important;
    /* Syne (la del manual) se reserva para títulos grandes tipo hero — a tamaños chicos
       de UI (nav, card-header, tablas) se ve forzada, ahí usamos Inter en negrita. */
    --vz-headings-font-family: 'Inter', sans-serif !important;
    /* El tema base "default" pone hkgrotesk y Poppins en estas dos, pero sus archivos
       nunca vinieron con la plantilla: el calendario, los menús laterales y los mapas
       caían a la genérica y el navegador pedía hkgrotesk-regular.woff con 404. */
    --vz-font-family-primary: 'Inter', sans-serif !important;
    --vz-font-family-secondary: 'Inter', sans-serif !important;

    --vz-border-radius: 0.75rem !important;
    --vz-border-radius-sm: 0.5rem !important;
    --vz-border-radius-lg: 1.25rem !important;
    --vz-border-radius-xl: 1.75rem !important;
    --vz-border-radius-xxl: 2.5rem !important;
}

/* Selector "Tema" del offcanvas de personalización — 7 acentos propios, no los
   genéricos de la plantilla (que además nunca se veían: antes esta regla no
   distinguía por valor y forzaba cerulean siempre, sin importar el swatch
   elegido). Cada uno cambia SOLO el color primario, nunca tipografía/layout —
   por diseño, para no romper la identidad de marca a medias. */
[data-theme-colors="default"] {
    --vz-primary: var(--arion-cerulean) !important;
    --vz-primary-rgb: 0, 114, 149 !important;
    --vz-primary-text-emphasis: var(--arion-indigo-dye) !important;
    --vz-primary-bg-subtle: rgba(0, 114, 149, 0.15) !important;
    --vz-primary-border-subtle: rgba(0, 114, 149, 0.3) !important;
    --vz-link-color: var(--arion-cerulean) !important;
    --vz-link-color-rgb: 0, 114, 149 !important;
    --vz-link-hover-color: var(--arion-indigo-dye) !important;
    --vz-link-hover-color-rgb: 32, 72, 107 !important;
}

[data-theme-colors="corporativo"] {
    --vz-primary: #2F4B7C !important;
    --vz-primary-rgb: 47, 75, 124 !important;
    --vz-primary-text-emphasis: #1D2F4F !important;
    --vz-primary-bg-subtle: rgba(47, 75, 124, 0.15) !important;
    --vz-primary-border-subtle: rgba(47, 75, 124, 0.3) !important;
    --vz-link-color: #2F4B7C !important;
    --vz-link-color-rgb: 47, 75, 124 !important;
    --vz-link-hover-color: #1D2F4F !important;
    --vz-link-hover-color-rgb: 29, 47, 79 !important;
}

[data-theme-colors="elegante"] {
    --vz-primary: #7A2E4D !important;
    --vz-primary-rgb: 122, 46, 77 !important;
    --vz-primary-text-emphasis: #4E1D32 !important;
    --vz-primary-bg-subtle: rgba(122, 46, 77, 0.15) !important;
    --vz-primary-border-subtle: rgba(122, 46, 77, 0.3) !important;
    --vz-link-color: #7A2E4D !important;
    --vz-link-color-rgb: 122, 46, 77 !important;
    --vz-link-hover-color: #4E1D32 !important;
    --vz-link-hover-color-rgb: 78, 29, 50 !important;
}

[data-theme-colors="creativo"] {
    --vz-primary: #C1502E !important;
    --vz-primary-rgb: 193, 80, 46 !important;
    --vz-primary-text-emphasis: #833318 !important;
    --vz-primary-bg-subtle: rgba(193, 80, 46, 0.15) !important;
    --vz-primary-border-subtle: rgba(193, 80, 46, 0.3) !important;
    --vz-link-color: #C1502E !important;
    --vz-link-color-rgb: 193, 80, 46 !important;
    --vz-link-hover-color: #833318 !important;
    --vz-link-hover-color-rgb: 131, 51, 24 !important;
}

[data-theme-colors="minimalista"] {
    --vz-primary: #495464 !important;
    --vz-primary-rgb: 73, 84, 100 !important;
    --vz-primary-text-emphasis: #2E353E !important;
    --vz-primary-bg-subtle: rgba(73, 84, 100, 0.15) !important;
    --vz-primary-border-subtle: rgba(73, 84, 100, 0.3) !important;
    --vz-link-color: #495464 !important;
    --vz-link-color-rgb: 73, 84, 100 !important;
    --vz-link-hover-color: #2E353E !important;
    --vz-link-hover-color-rgb: 46, 53, 62 !important;
}

[data-theme-colors="moderno"] {
    --vz-primary: #0E7C6B !important;
    --vz-primary-rgb: 14, 124, 107 !important;
    --vz-primary-text-emphasis: #0A5346 !important;
    --vz-primary-bg-subtle: rgba(14, 124, 107, 0.15) !important;
    --vz-primary-border-subtle: rgba(14, 124, 107, 0.3) !important;
    --vz-link-color: #0E7C6B !important;
    --vz-link-color-rgb: 14, 124, 107 !important;
    --vz-link-hover-color: #0A5346 !important;
    --vz-link-hover-color-rgb: 10, 83, 70 !important;
}

[data-theme-colors="interactivo"] {
    --vz-primary: #6A3FA0 !important;
    --vz-primary-rgb: 106, 63, 160 !important;
    --vz-primary-text-emphasis: #472A6B !important;
    --vz-primary-bg-subtle: rgba(106, 63, 160, 0.15) !important;
    --vz-primary-border-subtle: rgba(106, 63, 160, 0.3) !important;
    --vz-link-color: #6A3FA0 !important;
    --vz-link-color-rgb: 106, 63, 160 !important;
    --vz-link-hover-color: #472A6B !important;
    --vz-link-hover-color-rgb: 71, 42, 107 !important;
}

/* El azul/teal de marca es solo ACENTO (logo, botón, links, degradado superior).
   El fondo y las tarjetas deben quedar neutros oscuros — partimos de la paleta oscura
   NATIVA de panel base (ya está bien calibrada: body #1a1d21, header #292e32) y solo la
   oscurecemos un poco para que se sienta más parecida al mockup, en vez de inventar
   tonos nuevos que terminan sin relación con el resto del sistema de diseño. */
html[data-bs-theme="dark"] {
    --vz-body-bg: #16181c !important;
    --vz-secondary-bg: #212429 !important;
    --vz-tertiary-bg: #282c32 !important;
    --vz-border-color: #2d3138 !important;

    /* La barra superior NO debe pintarse del color primario (eso hace panel base con
       data-topbar="dark" por defecto) — debe quedar neutra, un poco más clara que el fondo. */
    --vz-header-bg: #24272c !important;
    --vz-header-border: #2d3138 !important;
    --vz-header-item-bg: #2d3138 !important;
    --vz-topbar-user-bg: #2d3138 !important;

    /* Segunda fila (nav horizontal de módulos) — mismo tono que la barra superior,
       para que no se note la costura entre ambas franjas. */
    --vz-topnav-bg: #24272c !important;
    --vz-topnav-item-color: #adb5bd !important;
    --vz-topnav-item-active-color: #fff !important;

    /* Color de íconos/texto de la topbar (logo excluido) — panel base los asume blancos
       porque su data-topbar="dark" normalmente pinta la barra de un color sólido.
       Como la neutralizamos, hay que fijar el contraste a mano. */
    --vz-header-item-color: rgba(255, 255, 255, 0.85) !important;
    --vz-header-item-sub-color: #adb5bd !important;
}

/* Presets de "Tono de fondo" (Identidad de marca, /configuracion/identidad) — mismos
   tokens que el bloque oscuro estándar de arriba, solo con la tonalidad rotada. Nunca
   un color libre: por eso son solo 2 variantes fijas, calibradas para mantener el
   mismo nivel de contraste contra el texto que ya usa el resto del sistema. */
html[data-bs-theme="dark"][data-fondo-tema="calido"] {
    --vz-body-bg: #1A1712 !important;
    --vz-secondary-bg: #241F17 !important;
    --vz-tertiary-bg: #2B251B !important;
    --vz-border-color: #302A1F !important;
    --vz-header-bg: #251F16 !important;
    --vz-header-border: #302A1F !important;
    --vz-header-item-bg: #302A1F !important;
    --vz-topbar-user-bg: #302A1F !important;
    --vz-topnav-bg: #251F16 !important;
}

html[data-bs-theme="dark"][data-fondo-tema="frio"] {
    --vz-body-bg: #12151C !important;
    --vz-secondary-bg: #1B1F28 !important;
    --vz-tertiary-bg: #21262F !important;
    --vz-border-color: #262C36 !important;
    --vz-header-bg: #1D2028 !important;
    --vz-header-border: #262C36 !important;
    --vz-header-item-bg: #262C36 !important;
    --vz-topbar-user-bg: #262C36 !important;
    --vz-topnav-bg: #1D2028 !important;
}

/* Mismo criterio en modo claro: la barra superior no debe pintarse del color
   primario (panel base lo hace por defecto con data-topbar="dark"), debe ser neutra. */
html[data-bs-theme="light"] {
    --vz-header-bg: #ffffff !important;
    --vz-header-border: #e9ebec !important;
    --vz-header-item-bg: #f3f3f9 !important;
    --vz-topbar-user-bg: #f3f3f9 !important;
    --vz-topnav-bg: #ffffff !important;
    --vz-topnav-item-color: #495057 !important;
    --vz-topnav-item-active-color: var(--arion-cerulean) !important;

    --vz-header-item-color: #495057 !important;
    --vz-header-item-sub-color: #878a99 !important;
}

/* Logo: la versión clara (texto blanco) solo se ve sobre fondo oscuro; en modo
   claro la barra es blanca, así que se necesita la versión con texto oscuro. */
.logo-for-light-theme { display: none; }
html[data-bs-theme="light"] .logo-for-dark-theme { display: none; }
html[data-bs-theme="light"] .logo-for-light-theme { display: inline; }

/* Badges de estado (bg-X-subtle + text-X, patrón usado en todo el sistema):
   en modo claro el par de colores de fábrica de Velzon no cumple contraste
   mínimo de accesibilidad (medido con la fórmula WCAG) — warning 1.62:1,
   success 2.29:1, info 2.62:1, danger 2.68:1, secondary 3.46:1, todos por
   debajo del mínimo de 4.5:1. Se oscurece SOLO el texto dentro de .badge
   (mismo tono, mismo fondo pastel) para no afectar botones/alertas/íconos
   que usan esas mismas clases .text-X/.bg-X-subtle en otros contextos. */
html[data-bs-theme="light"] .badge.text-warning { color: #8d692b !important; }
html[data-bs-theme="light"] .badge.text-success { color: #077a6a !important; }
html[data-bs-theme="light"] .badge.text-info { color: #1e72a0 !important; }
html[data-bs-theme="light"] .badge.text-danger { color: #b24b35 !important; }
html[data-bs-theme="light"] .badge.text-secondary { color: #2d65cd !important; }

/* El nav horizontal de módulos puede traer muchos items (según licencia/permisos).
   Se queda en una sola línea (como pide el diseño) y se desliza horizontalmente
   en vez de cortarse fuera del margen o encimarse con el contenido de abajo. */
.app-menu.navbar-menu {
    /* Ese padding es el que panel base usa para el sidebar VERTICAL — en horizontal
       infla la barra ~30px de más y desalinea el contenido de abajo. */
    padding: 0 !important;
}
.app-menu.navbar-menu #navbar-nav {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    /* Ojo: NO poner scroll-behavior:smooth aquí. Se probó para animar el salto
       de las flechas y el desplazamiento dejó de ocurrir por completo — ni con
       scrollBy({behavior:'smooth'}) ni asignando scrollLeft, con saltos de 50,
       100, 107, 300 y 780px, todos quedaban en 0. El salto instantáneo es
       fiable en todos lados y en un menú no se echa de menos la animación. */
}
/* El nowrap de arriba impide que los ITEMS salten de fila, pero no que el TEXTO
   de un item se parta en dos líneas: como flex-item, cada .nav-item se encoge
   por defecto (flex-shrink:1) hasta que su etiqueta ya no cabe en una línea, y
   entonces el nombre rompe adentro del propio botón. Con nombres largos
   ("Comunicados internos", "Checador Biométrico") eso hacía crecer toda la
   barra al doble de alto. Se les quita el encogimiento y se fuerza una sola
   línea: si el conjunto ya no cabe, se desliza — que es justo para lo que está
   el overflow-x de arriba. */
.app-menu.navbar-menu #navbar-nav > .nav-item {
    flex: 0 0 auto;
}
.app-menu.navbar-menu #navbar-nav > .nav-item > .nav-link {
    white-space: nowrap;
}
/* Señal de que el menú sigue más allá del borde. Con una sola fila y la barra
   de scroll de 1px de arriba (deliberadamente casi invisible), un módulo
   cortado en el filo se lee como "ya no hay más" en vez de "desliza": el item
   siguiente queda inalcanzable sin que nada invite a buscarlo. El degradado se
   pinta sobre el contenedor (no sobre el <ul>, que es el que scrollea, o se
   desplazaría junto con los items) y las clases las pone/quita el JS del
   layout según la posición real del scroll — así no aparece cuando todo cabe,
   ni del lado al que ya no queda nada. */
/* El ancla es el .container-fluid interno, NO .navbar-menu: en layout
   horizontal Velzon le da position:fixed con margin-top:70px, y cambiarla a
   relative lo devuelve al flujo — la barra se despega del topbar y deja un
   hueco. El .container-fluid es un div normal, hijo directo del <ul>, así que
   coincide en ancho con lo que scrollea. */
.app-menu.navbar-menu .container-fluid {
    position: relative;
}
.app-menu.navbar-menu .container-fluid::before,
.app-menu.navbar-menu .container-fluid::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 4.5rem;
    pointer-events: none;
    opacity: 0;
    transition: opacity .15s ease;
    z-index: 2;
}
.app-menu.navbar-menu .container-fluid::before {
    left: 0;
    background: linear-gradient(to right, var(--vz-topnav-bg), transparent);
}
.app-menu.navbar-menu .container-fluid::after {
    right: 0;
    background: linear-gradient(to left, var(--vz-topnav-bg), transparent);
}
.app-menu.navbar-menu.arion-nav-desliza-inicio .container-fluid::before,
.app-menu.navbar-menu.arion-nav-desliza-fin .container-fluid::after {
    opacity: 1;
}
/* Flechas para deslizar. El degradado solo AVISA; sin algo clicable no hay
   forma de llegar al módulo cortado: la barra de scroll del nav es de 1px y la
   rueda del ratón no desplaza en horizontal. Van encima del degradado (z-index
   mayor) y aparecen con las mismas clases de estado, así que nunca sale una
   flecha hacia un lado donde ya no queda menú. */
.arion-nav-flecha {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2rem;
    z-index: 3;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--vz-topnav-item-color);
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
}
.arion-nav-flecha:hover {
    color: var(--vz-topnav-item-active-color);
}
.arion-nav-flecha-inicio { left: 0; }
.arion-nav-flecha-fin { right: 0; }
.app-menu.navbar-menu.arion-nav-desliza-inicio .arion-nav-flecha-inicio,
.app-menu.navbar-menu.arion-nav-desliza-fin .arion-nav-flecha-fin {
    display: flex;
}
/* Ojo con "scrollbar-width" (Firefox y Chromium modernos): en cuanto se declara —
   con CUALQUIER valor, incluido "thin" — el navegador ignora por completo el
   pixelaje fino de ::-webkit-scrollbar y usa su propio ancho preestablecido
   (~10px para "thin", nada de "delgado" de verdad). Por eso NO se declara aquí:
   dejamos que solo mande ::-webkit-scrollbar, que sí permite un valor exacto. */
.app-menu.navbar-menu #navbar-nav::-webkit-scrollbar {
    height: 1px;
}
.app-menu.navbar-menu #navbar-nav::-webkit-scrollbar-thumb {
    background-color: rgba(0, 114, 149, 0.35);
}
.app-menu.navbar-menu #navbar-nav::-webkit-scrollbar-track {
    background-color: transparent;
}

/* .page-content asume un header de una sola fila (70px) — con la segunda fila del
   nav de módulos el header real mide más, y el contenido quedaba encimado con el
   menú (y su dropdown en hover terminaba tapado). Empujamos el contenido lo que
   el nav realmente mide (marcado vía body.has-subnav, ver panel.blade.php).
   Solo aplica en escritorio: bajo 1024.1px esa segunda fila no existe en el
   flujo (se oculta y solo se abre como overlay con el botón ☰), así que aquí
   sumaba 134px de más encima del padding-top de abajo — un hueco enorme entre
   el header y el título en TODAS las páginas con submenú (Inventario, Ventas,
   etc.), aunque sin submenú (Roles) no se notaba. */
@media (min-width: 1024.1px) {
    body.has-subnav .page-content {
        margin-top: 134px !important;
    }
}

/* El footer flotaba con position:absolute: en páginas con poco contenido (hub) quedaba
   "flotando" a media pantalla, y en páginas con columnas de alturas distintas (ej. el
   panel de RRHH del dashboard) terminaba encimado con la última card. Patrón sticky-footer
   con flexbox: nunca se puede superponer, y en páginas cortas igual queda pegado abajo. */
.main-content {
    display: flex;
    flex-direction: column;
    /* .main-content arranca en y:0 (el header es position:fixed, no le quita espacio
       de flujo) — el hueco del header lo genera el margin-top de .page-content, DESDE
       ADENTRO de esta caja. Por eso min-height es 100vh completo, no 100vh menos el
       header: si le restamos el header aquí Y con el margin-top de adentro, se resta
       dos veces y el footer se queda corto de la parte de abajo real. */
    min-height: 100vh;
}
.page-content {
    flex: 1 0 auto;
    /* panel base reserva 69px de padding-top pensado para SU propio widget de "page title"
       (breadcrumb + título con caja/sombra) — nosotros armamos el título a mano dentro
       del contenido, así que ese padding se sumaba al margin-top del header y dejaba
       un hueco enorme e injustificado arriba de cada página. */
    padding-top: 24px !important;
    padding-bottom: calc(var(--vz-grid-gutter-width) * .5) !important;
}
/* Bajo 1024.1px el menú horizontal de módulos deja de ocupar una fila propia
   (se colapsa dentro del topbar) y #page-topbar, fijo (position:fixed), se
   queda con ~71px de alto sin ningún elemento en el flujo normal que empuje
   el contenido hacia abajo — con solo 24px de padding-top, el título real de
   CADA página (page-title.blade.php: la flecha + h3 con el nombre) queda
   literalmente detrás del header, invisible, en cualquier tablet o celular.
   Pasa en TODAS las páginas, no solo el hub — el contenido secundario (texto
   debajo del título) sí se alcanza a ver, así que a simple vista parece que
   "no pasa nada" hasta que se busca el título mismo. A partir de 1024.1px sí
   aparece esa fila extra del menú horizontal y da espacio de sobra (mismo
   breakpoint que usa Velzon para esta transición en app.min.css). */
@media (max-width: 1024.1px) {
    .page-content { padding-top: 100px !important; }
}
/* Botón hamburguesa del menú de módulos — solo tiene sentido bajo 1024px,
   que es donde ese menú se colapsa (ver .page-content arriba, mismo
   breakpoint). En desktop el menú ya se ve siempre en su propia fila. */
.arion-topnav-toggle { display: none; }
@media (max-width: 1024.1px) {
    .arion-topnav-toggle { display: inline-flex !important; }
}
.footer {
    position: static !important;
    left: auto !important;
    flex-shrink: 0;
}

/* Títulos grandes tipo hero (login, saludo del hub): Syne, como en el manual.
   Todo lo demás (card-header, tablas, nav) se queda en Inter bold — más legible a tamaño chico. */
.font-display {
    font-family: 'Syne', sans-serif;
    font-weight: 700;
}

.auth-page-content h3 { font-size: 1.5rem; }

/* El panel de Apariencia (offcanvas) se quedaba con el transform de "oculto" (fuera
   de pantalla) aunque Bootstrap ya le hubiera puesto la clase .show — se veía nomás
   el fondo oscuro (backdrop) sin el panel. Se fuerza a mano. */
#theme-settings-offcanvas.show {
    transform: none !important;
}

/* Los radios/checkboxes marcados se quedaban en blanco sobre blanco (invisibles) pese
   a que la regla de panel base para :checked ya apunta al color primario — se fuerza a
   mano para garantizar que se vea, sea cual sea la causa exacta de la pelea de cascada. */
.form-check-input:checked {
    background-color: var(--arion-cerulean) !important;
    border-color: var(--arion-cerulean) !important;
}

/* Mismo problema con los grupos tipo botón (.btn-check + label.btn-outline-*): el
   estado marcado no se pintaba sólido. Se fuerza igual, por color semántico. */
.btn-check:checked + .btn-outline-success {
    background-color: var(--vz-success) !important;
    color: #fff !important;
}
.btn-check:checked + .btn-outline-danger {
    background-color: var(--vz-danger) !important;
    color: #fff !important;
}
.btn-check:checked + .btn-outline-primary {
    background-color: var(--arion-cerulean) !important;
    color: #fff !important;
}

/* Radio grande estilo mockup (anillo + punto), para selects de Estado — no el
   radio chico de Bootstrap por defecto, ni el botón sólido tipo chip. */
.radio-lg {
    width: 1.5rem !important;
    height: 1.5rem !important;
    border-width: 2px !important;
    background-image: none !important;
}
.radio-lg:checked {
    background-color: transparent !important;
    border-color: var(--arion-cerulean) !important;
    box-shadow: inset 0 0 0 5px var(--arion-cerulean);
}

/* Switches (permisos de Roles): más grandes que el default de Bootstrap (se veían
   diminutos) y que se pinten de verde al activarse, como el mockup. */
.form-switch .form-check-input {
    width: 2.75rem !important;
    height: 1.5rem !important;
    cursor: pointer;
}
.form-switch .form-check-input:checked {
    background-color: var(--vz-success) !important;
    border-color: var(--vz-success) !important;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e") !important;
}

/* El switch más ancho de arriba (2.75rem) deja su label pegado con 0px de separación
   en TODO el sistema (Configuración POS, Roles, Agenda pública, etc. — no es un bug de
   una sola pantalla). Bootstrap calcula el padding-left del .form-check en base al ancho
   default del switch, no al agrandado, así que el texto siempre queda tocando el track. */
.form-switch .form-check-label {
    margin-left: 0.4rem;
}

/* Encabezado sticky de tablas dentro de modales (ej. matriz de permisos de Roles):
   las celdas del thead son transparentes por defecto, así que al hacer scroll las
   filas de abajo se transparentaban a través del encabezado "fijo". */
.modal thead.sticky-top th {
    background-color: var(--vz-secondary-bg);
}

/* panel base oculta .navbar-brand-box (el logo) bajo 767.98px porque en su diseño original
   ese logo vive en el sidebar vertical, que aquí no existe (todo el sistema es horizontal-only).
   Sin esta regla el logo desaparece por completo en celular. */
@media (max-width: 767.98px) {
    [data-layout="horizontal"] .navbar-brand-box.horizontal-logo {
        display: flex !important;
        align-items: center;
        padding: 0 0.5rem 0 0 !important;
    }
}

/* Barras de filtro (Sucursales, Usuarios...): en celular los inputs/select ya ocupan
   el 100% del ancho (comportamiento nativo de .form-control/.form-select), pero los
   botones "Aplicar/Limpiar/Filtros" se quedaban angostos y pegados a la izquierda
   (ancho automático) — se veían desordenados comparados con el resto de la barra. */
@media (max-width: 767.98px) {
    .filter-btn {
        width: 100%;
    }
}

/* Botones chicos tipo "Modificar" (.btn-sm.rounded-pill, usados en tablas y tarjetas
   de Roles/Usuarios/Sucursales): a 27px de alto con 11px de letra son muy difíciles
   de tocar en celular — se agranda el objetivo táctil solo en anchos chicos. */
@media (max-width: 767.98px) {
    .btn-sm {
        min-height: 36px;
        padding: 0.4rem 0.9rem;
        font-size: 0.8125rem;
    }
}

/* Header de card con título + botones de acción (patrón "card-header d-flex
   justify-content-between" usado en prácticamente todas las listas — Clientes,
   CRM, Pagos, Compras, etc.): en celular no cabe todo en una sola fila, y el
   grupo de botones terminaba ENCIMADO sobre el título en vez de bajar de línea
   (justify-content-between no envuelve, solo empuja los extremos). Se apilan
   verticalmente solo en celular; en tablet/desktop sigue una sola fila. */
@media (max-width: 575.98px) {
    .card-header.d-flex.justify-content-between {
        flex-direction: column;
        align-items: flex-start !important;
        gap: 0.5rem;
    }
    .card-header.d-flex.justify-content-between > div {
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
        width: 100%;
    }
    .card-header.d-flex.justify-content-between > div > .btn {
        margin: 0 !important;
    }
}

/* vue-select (v2.6.4, no usa las variables --vs-* de las versiones nuevas) inyecta su
   propio <style> por JS cuando el componente se monta — eso pasa DESPUÉS de que este
   archivo ya cargó, así que gana el empate de cascada aunque este archivo esté "bien"
   escrito. Hace falta !important para garantizar que gane pase lo que pase. */
.v-select .dropdown-toggle {
    background-color: var(--vz-secondary-bg) !important;
    border: 1px solid var(--vz-border-color) !important;
    border-radius: var(--vz-border-radius) !important;
    min-height: calc(1.5em + 1rem + 2px) !important;
}
.v-select input.form-control {
    background-color: transparent !important;
    color: var(--vz-body-color) !important;
    box-shadow: none !important;
    border: none !important;
}
.v-select .selected-tag {
    background-color: var(--arion-cerulean) !important;
    color: #fff !important;
    border-radius: .4rem !important;
    border: none !important;
}
.v-select .selected-tag .close {
    color: #fff !important;
    opacity: .8 !important;
}
.v-select .dropdown-menu {
    background-color: var(--vz-secondary-bg) !important;
}
.v-select .dropdown-menu li > a {
    color: var(--vz-body-color) !important;
}
.v-select .dropdown-menu li.highlight > a,
.v-select .dropdown-menu li > a:hover {
    background-color: var(--arion-cerulean) !important;
    color: #fff !important;
}
.v-select .open-indicator:before {
    border-color: var(--vz-body-color) !important;
}

/* Saludo del hub — es el elemento hero de la página, debe dominar visualmente */
.hub-greeting { font-size: 3rem; }
@media (max-width: 575.98px) {
    .hub-greeting { font-size: 2rem; }
}

.hub-header { padding-top: 1.5rem; }

/* Hub de módulos: tiles cuadrados con ícono centrado, pegados entre sí como en el mockup */
.hub-grid {
    max-width: 62rem;
    margin: 0 auto;
}
.hub-tile {
    display: block;
    width: 7.5rem;
}
.hub-tile-icon {
    width: 5.5rem;
    height: 5.5rem;
    margin-left: auto;
    margin-right: auto;
    transition: transform .15s ease, background-color .15s ease;
}
.hub-tile-icon .card-body { padding: 0; }
.hub-tile:not(.hub-tile--proximamente):hover .hub-tile-icon {
    transform: translateY(-3px);
    background-color: var(--vz-tertiary-bg);
}
.hub-tile-label {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    min-height: 2.4em;
    line-height: 1.2;
    font-size: .9375rem;
    font-weight: 500;
}

/* Tile de un módulo anunciado pero sin construir: no es enlace, no reacciona al hover
   y lleva la etiqueta encima del ícono para no chocar con el nombre de abajo. */
.hub-tile--proximamente { cursor: default; }
.hub-tile--proximamente .hub-tile-icon i { opacity: .55; }
.hub-tile-badge {
    position: absolute;
    top: -.6rem;
    left: 50%;
    transform: translateX(-50%);
    font-size: .625rem;
    white-space: nowrap;
}

/* El avatar-title de panel base espera un contenedor .avatar-xs que le dé tamaño fijo;
   usado suelto en la topbar se estira y la letra sale ovalada, no circular. */
.avatar-initial-circle {
    width: 32px !important;
    height: 32px !important;
    min-width: 32px;
    flex-shrink: 0;
}

/* Calendario de Citas (FullCalendar) — las citas de 30 min entraban en el modo
   "fc-timegrid-event-short" de FullCalendar, que colapsaba .fc-event-main-frame a
   ~1px de alto con overflow:hidden (probablemente por el reset de line-height/
   box-sizing de Bootstrap 5 encima del CSS de FullCalendar). El resultado: el bloque
   de color se veía bien pero el nombre del paciente/hora quedaba recortado a 0px de
   alto — invisible aunque el texto sí estuviera en el DOM. */
.fc-timegrid-event-harness {
    min-height: 34px !important;
}
.fc-timegrid-event .fc-event-main,
.fc-timegrid-event .fc-event-main-frame {
    height: auto !important;
    min-height: 30px !important;
    overflow: visible !important;
}
.fc-timegrid-event .fc-event-title-container,
.fc-timegrid-event .fc-event-title {
    height: auto !important;
    overflow: visible !important;
    white-space: normal !important;
    line-height: 1.2 !important;
}
.fc-timegrid-event .fc-event-time {
    flex-shrink: 0 !important;
}

/* Iconos de redes sociales: colores de marca fijos, independientes del primario del sitio */
.btn-social-facebook { background-color: #3b5998; border-color: #3b5998; color: #fff; }
.btn-social-google { background-color: #ea4335; border-color: #ea4335; color: #fff; }
.btn-social-github { background-color: #24292e; border-color: #24292e; color: #fff; }
.btn-social-twitter { background-color: #1da1f2; border-color: #1da1f2; color: #fff; }

/* SweetAlert con buttonsStyling:false: sus botones heredan clases de Bootstrap
   pero pierden el margen propio, y "Sí / No" salían pegados. */
.swal2-actions { gap: .5rem; }

/* DatePicker (vue2-datepicker) es inline-block de 210px: cuando su columna es
   ancha (móvil, col-md-auto) se acomodaba en la misma línea que su etiqueta,
   encimado. Bajo una etiqueta siempre va en su propio renglón. */
.form-label + .mx-datepicker { display: block; }

/* El .row de .modal-body (row g-3) tiene margen superior negativo y tapaba la
   X del encabezado: el clic caía en el cuerpo y el modal no se cerraba. */
.modal-header { position: relative; z-index: 2; }

/* Pieza del Dashboard: junto a los KPIs en pantallas grandes (d-none d-lg-block
   en el Blade la oculta debajo de lg). Los WebP fuente miden 540px de ancho
   (ver public/panel/images/piezas/), hay que topar el tamaño o se ve enorme. */
.dashboard-piece-col { width: 11rem; }
.dashboard-piece { max-width: 100%; height: auto; }

/* Tarjetas de Roles: pieza del rol en vez del icono genérico bx-user. Los WebP
   rol-*-negra/plata.webp miden 160px de alto (ver public/panel/images/piezas/),
   se topan al tamaño del icono que reemplazan. */
.rol-card-pieza { max-height: 3.5rem; width: auto; }

/* Pieza del módulo: en el Inicio de cada módulo, a la izquierda de la primera
   fila de KPIs, en pantallas grandes (d-none d-lg-block en el Blade/Vue la
   oculta debajo de lg — maquetado "Solicitudes - Inicio"). Los WebP fuente
   modulo-*-claro/oscuro.webp miden 360px cuadrados; se topan a ~200px de alto
   (el propio documento de maquetado pide que la pieza no le quite
   protagonismo a los datos). */
/* Tamaño: la pieza mide lo mismo que la fila de tarjetas de al lado (pedido
   del usuario, 2026-09-18: antes se salía por arriba y por abajo). La columna
   se estira a la altura de la fila (align-self) y la imagen va absoluta para
   no empujar esa altura. El dibujo de las piezas más altas (rey, reina) ocupa
   del 4% al 88% del WebP, así que la imagen mide 119% de la fila y sube 5%:
   la pieza toca el borde de arriba de la tarjeta y su base el de abajo. Las
   demás son más bajas a la misma escala, como en un tablero de verdad. */
.modulo-piece-col { width: 8rem; align-self: stretch; position: relative; }
.modulo-piece {
    position: absolute;
    top: -5%;
    left: 50%;
    height: 119%;
    width: auto;
    max-width: none;
    transform: translateX(-50%);
}
/* Los bordes del tablerito bajo la pieza se notaban como un recuadro contra
   el fondo de la página: se desvanecen a los lados y abajo con una máscara
   (dos degradados que se intersectan). La pieza ocupa el 32-68% del ancho y
   termina al ~82% del alto, así que la máscara no la toca (pedido del
   usuario, 2026-09-18). */
.modulo-piece {
    -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 16%, #000 84%, transparent 100%), linear-gradient(to bottom, #000 88%, transparent 100%);
    -webkit-mask-composite: source-in;
    mask-image: linear-gradient(to right, transparent 0%, #000 16%, #000 84%, transparent 100%), linear-gradient(to bottom, #000 88%, transparent 100%);
    mask-composite: intersect;
}

/* Login y demás pantallas de acceso: el maquetado ("Iniciar sesión") muestra
   bg-login.jpg (las ondas azules) tal cual. La plantilla le ponía encima
   .bg-overlay con un degradado del color primario al 90% y la foto casi no se
   veía, así que el fondo parecía liso. */
.auth-one-bg .bg-overlay { opacity: 0; }
/* Video de fondo de la parte azul del login (2026-09-21): cubre la franja sin
   deformarse; la imagen del tema queda detrás por si el video no carga. */
.auth-one-bg { overflow: hidden; background-image: url(../images/bg-login-video.jpg); }
.auth-one-bg .auth-video-fondo {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
    .auth-one-bg .auth-video-fondo { display: none; }
}
/* El acceso en el celular (2026-09-23, lo reportó el usuario). En pantalla
   angosta la plantilla dejaba el video como una franja de 280 px que se
   cortaba a media tarjeta, la onda blanca asomaba por un costado y el pie de
   página quedaba partido contra el borde de abajo. Aquí el video pasa a ser el
   fondo de toda la pantalla, con un velo que deja legibles el logo, la tarjeta
   y el pie. */
@media (max-width: 575.98px) {
    .auth-page-wrapper {
        position: relative;
        min-height: 100vh;
        display: flex;
        flex-direction: column;
        padding-top: 1.5rem !important;
    }
    .auth-page-wrapper .auth-one-bg { height: 100%; }
    /* La onda de la plantilla está pensada para el corte de la franja: sin
       franja no tiene nada que rematar y solo asomaba por la izquierda. */
    .auth-page-wrapper .auth-one-bg .shape { display: none; }
    .auth-page-wrapper .auth-one-bg::after {
        content: "";
        position: absolute;
        inset: 0;
        background: linear-gradient(180deg, rgba(10, 14, 20, .3) 0%, rgba(10, 14, 20, .42) 45%, rgba(10, 14, 20, .78) 100%);
    }
    /* El fondo va posicionado y el pie no: sin esto el video se pinta encima
       del pie y el aviso de derechos desaparece. */
    .auth-page-wrapper .footer { position: relative; }
    .auth-page-wrapper .auth-page-content {
        flex: 1 0 auto;
        padding-bottom: 1.5rem;
    }
    .auth-page-wrapper .auth-logo img { height: 44px; }
    .auth-page-wrapper .auth-page-content .card { margin-top: 1rem !important; }
    /* 16 px de aire a los lados: con los 12 de Bootstrap la tarjeta casi toca
       el borde del teléfono. */
    .auth-page-wrapper .auth-page-content .container { padding-inline: 1rem; }
}

/* Agenda — los bloques de "No disponible" se pintan como FONDO de la franja
   (display:background), no como un evento en columna. Cuando competían por
   columna, uno de cinco horas tocaba todas las citas de la tarde y el reparto
   de columnas las encadenaba en un solo grupo: el ancho se dividía entre todas
   a la vez y los nombres quedaban de una letra de ancho (agenda de Lemus,
   usuario 2026-09-25). El rayado los distingue de una franja libre sin
   competir con el color de las citas. */
.fc-bg-event.evento-no-disponible {
    /* Mas marcado que el primer intento, que se confundia con una franja
       libre (usuario, 2026-09-25): rayas mas oscuras y borde a los lados. */
    /* --rayas-rgb lo pone la agenda con el color de la categoría del bloqueo
       (2026-10-09); sin categoría queda el gris de siempre. */
    background: repeating-linear-gradient(
        45deg,
        rgba(var(--rayas-rgb, 90, 98, 104), .42),
        rgba(var(--rayas-rgb, 90, 98, 104), .42) 7px,
        rgba(var(--rayas-rgb, 90, 98, 104), .20) 7px,
        rgba(var(--rayas-rgb, 90, 98, 104), .20) 14px
    ) !important;
    border-left: 3px solid rgba(var(--rayas-rgb, 90, 98, 104), .75) !important;
    border-right: 3px solid rgba(var(--rayas-rgb, 90, 98, 104), .75) !important;
    opacity: 1 !important;
    cursor: pointer;
}
.fc-bg-event.evento-no-disponible .fc-event-title {
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: #343a40;
    background: rgba(255, 255, 255, .82);
    border-radius: 3px;
    padding: 2px 6px;
    margin: 3px;
    display: inline-block;
    font-style: normal;
}

/* Agenda en pantalla chica — la vista Semana metia siete dias en 375 px, o sea
   unos 45 px por dia, y con dos citas encimadas el nombre salia escrito hacia
   abajo, una letra por renglon (usuario, 2026-09-25). NO se le quita la vista a
   nadie: se le da a cada dia el ancho que necesita para leerse y la rejilla se
   desliza de lado, que es como lo resuelven las agendas en telefono. El Mes se
   queda igual: ahi cada celda es un dia y no hay nombres que leer. */
@media (max-width: 767.98px) {
    /* 7 dias * 130 px mas la columna de las horas. La cabecera y el cuerpo
       llevan el mismo ancho o los dias se descuadran del encabezado al
       desplazar; FullCalendar ya sincroniza los dos scrollers entre si. */
    .fc-timeGridWeek-view .fc-col-header,
    .fc-timeGridWeek-view .fc-timegrid-body,
    .fc-timeGridWeek-view .fc-timegrid-body table,
    .fc-timeGridWeek-view .fc-scrollgrid-sync-table,
    .fc-timeGridWeek-view .fc-timegrid-slots table {
        min-width: 980px !important;
    }
    /* La columna de las horas se queda pegada a la izquierda al deslizar. Si
       se perdiera no seria grave —cada cita lleva su hora escrita dentro—
       pero se lee mucho mejor con ella a la vista. */
    .fc-timeGridWeek-view .fc-timegrid-slot-label,
    .fc-timeGridWeek-view .fc-timegrid-axis {
        position: sticky;
        left: 0;
        z-index: 4;
        background: var(--vz-secondary-bg, #fff);
        box-shadow: 1px 0 0 rgba(0, 0, 0, .12);
    }
}

/* Logo del negocio en la barra superior. Antes era height="26" fijo: un logo
   cuadrado o apilado quedaba de 26x26, diminuto. Se mide por caja: hasta 48px
   de alto (la barra mide 70) y 170px de ancho, sin deformarse. El margen
   blanco que traen muchos logos se recorta al subirlos (LogoDelNegocio). */
.navbar-brand-box .logo-negocio {
    width: auto;
    height: auto;
    max-height: 48px;
    max-width: 170px;
    object-fit: contain;
    vertical-align: middle;
}
/* En el tema oscuro el logo va sobre una pastilla blanca: casi todos traen
   fondo blanco o letras oscuras, y sobre la barra oscura se veían como un
   parche blanco o no se leían. */
html[data-bs-theme="dark"] .navbar-brand-box .logo-negocio {
    background: #fff;
    border-radius: 6px;
    padding: 3px 6px;
    box-sizing: content-box;
    max-height: 42px;
}
/* El nombre junto a un logo que no es horizontal (Business::logoEsHorizontal). */
.navbar-brand-box a.logo:has(.logo-negocio-nombre) {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}
.logo-negocio-nombre {
    font-weight: 700;
    font-size: 15px;
    line-height: 1.2;
    color: var(--vz-heading-color, var(--vz-body-color));
    max-width: 220px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
@media (max-width: 767.98px) {
    .navbar-brand-box .logo-negocio { max-height: 38px; max-width: 110px; }
    html[data-bs-theme="dark"] .navbar-brand-box .logo-negocio { max-height: 32px; }
    .logo-negocio-nombre { font-size: 13px; max-width: 120px; white-space: normal;
        display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
}