/* ============================================================
   TapBox · capa de marca para el panel Filament
   ============================================================ */
@import url('/fonts/tapbox/tapbox-fuentes.css');

:root {
    --tb-navy: #20282D;
    --tb-blue: #257554;
    --tb-display: 'Schibsted Grotesk', 'Inter', system-ui, sans-serif;
    --tb-mono: 'IBM Plex Mono', ui-monospace, monospace;
}

.fi-header-heading,
.fi-section-header-heading,
.fi-section-heading,
.fi-modal-heading,
.fi-ta-header-heading,
.fi-wi-stats-overview-stat-value,
.fi-form-section-header-heading {
    font-family: var(--tb-display) !important;
    letter-spacing: -0.01em;
}

.fi-topbar .fi-logo,
.fi-sidebar-header .fi-logo { font-family: var(--tb-display); }

.fi-btn { border-radius: 0.7rem; }

.fi-sidebar-item-active .fi-sidebar-item-button { box-shadow: inset 3px 0 0 0 var(--tb-blue); }

.fi-wi-stats-overview-stat-label { font-family: var(--tb-mono); letter-spacing: 0.04em; }

.tb-logo-light { display: none !important; }
.dark .tb-logo-dark { display: none !important; }
.dark .tb-logo-light { display: block !important; }

.fi-tabs-item-label { color: #111722; }
.dark .fi-tabs-item-label { color: #ffffff; }

/* — Inicio: cabecera de bienvenida (hero) — */
.tb-hero { position: relative; overflow: hidden; border-radius: 18px; padding: 30px 32px; color: #fff;
    background: linear-gradient(168deg, #2A343A 0%, #20282D 62%, #171D21 100%);
    border: 1px solid rgba(255,255,255,.08); box-shadow: 0 24px 50px -30px rgba(0,0,0,.55); }
/* Filo verde superior: firma de marca sin recurrir a degradados de color. */
.tb-hero::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 2px;
    background: linear-gradient(90deg, #70C7A3, rgba(112,199,163,0)); }
.tb-hero__mark { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; flex-wrap: wrap; }
.tb-hero__mark img { height: 28px; width: auto; display: block; }
/* X para cerrar el menú lateral (solo móvil; no tapa los logos, va a la derecha) */
.tb-sidebar-close { display: none; }
@media (max-width: 1024px) {
    .tb-sidebar-close {
        display: inline-flex; align-items: center; justify-content: center;
        margin-inline-start: auto; flex: none;
        width: 36px; height: 36px; border-radius: 9px;
        border: 1px solid var(--tb-d-border, #e2e8f0); background: transparent;
        color: inherit; cursor: pointer;
    }
    .tb-sidebar-close:active { transform: scale(.94); }
}

/* ═══════════════════════════════════════════════════════════════════════
   FIRMA DE MARCA: el negocio manda, TapBox firma

   El panel es del cliente, así que su logo es el que se ve; TapBox queda al
   lado, más chico y en gris, detrás de una línea fina. La versión anterior
   ponía las dos marcas del mismo tamaño y con un "Usa" entre medio: el
   proveedor pesaba más que el dueño de casa, y la frase se leía cortada.
   ═══════════════════════════════════════════════════════════════════════ */
.tb-brand { display: inline-flex; align-items: center; gap: .7rem; line-height: 1; }

/* Logo del negocio: es el protagonista. El fondo blanco con esquinas
   redondeadas sirve para los logos de tinta oscura, que sobre el tema oscuro
   desaparecerían. */
.tb-brand__cliente {
    height: 2.5rem; width: auto; max-width: 150px; display: block;
    border-radius: 7px; background: #fff; padding: 3px 7px; box-sizing: content-box;
}

/* La línea fina: separa sin decir nada y aguanta cualquier ancho de logo. */
.tb-brand__linea { width: 1px; height: 2.1rem; background: currentColor; opacity: .17; flex: none; }

.tb-brand__firma { display: inline-flex; flex-direction: column; gap: .18rem; }

/* "FUNCIONA CON": micro-texto en versalitas. Tiene que leerse, no llamar la
   atención — por eso va chico, espaciado y apagado. */
.tb-brand__nota {
    font-family: 'Schibsted Grotesk', 'Inter', ui-sans-serif, sans-serif;
    font-size: .5625rem; font-weight: 600; letter-spacing: .11em;
    text-transform: uppercase; opacity: .5; white-space: nowrap;
}

.tb-brand__tapbox { display: inline-flex; align-items: center; gap: .3rem; opacity: .82; }
.tb-brand__tapbox img { height: 1.15rem; width: auto; display: block; }

.tb-brand__palabra {
    font-family: 'Schibsted Grotesk', 'Inter', ui-sans-serif, sans-serif;
    font-weight: 600; font-size: .9375rem; letter-spacing: -.02em; color: currentColor;
}

/* Logo del negocio en la barra del celular. Oculto en el computador, donde el
   menú lateral ya lo muestra fijo; ahí repetirlo sería ruido.
   El corte es el mismo que usa Filament para plegar el menú (1024px). */
.tb-brand-movil { display: none; }
@media (max-width: 1023px) {
    .tb-brand-movil { display: inline-flex; align-items: center; flex: none; margin-inline-end: .5rem; }
    .tb-brand-movil img {
        /* Se mide en vw: en un teléfono angosto el logo cede ancho solo, en vez
           de dejar el buscador reducido a "Bus". */
        height: 1.75rem; width: auto; max-width: min(88px, 23vw); display: block;
        border-radius: 6px; background: #fff; padding: 2px 5px; box-sizing: content-box;
    }

    /* El botón del menú va primero, como en cualquier app: el pulgar lo busca
       en el borde. El logo se dibuja antes en el HTML, así que se reordena acá. */
    .fi-topbar-open-sidebar-btn, .fi-topbar-close-sidebar-btn { order: -1; }

    /* ── Buscador plegado a lupa ──────────────────────────────────────────
       En 375px no caben el logo, el buscador y los tres botones: el buscador
       quedaba reducido a 41px útiles, mostrando "Bu". Plegado a la lupa deja
       sitio al logo, y al tocarlo se abre con espacio real para escribir.

       La zona de toque es la ETIQUETA del campo, no el icono: pulsar el icono
       no enfoca nada (es un SVG decorativo), mientras que una etiqueta enfoca
       su campo por sí sola, sin una línea de JavaScript. Sigue leyéndose en
       los lectores de pantalla porque se esconde con sangría, no se elimina. */
    /* Filament separa los elementos de la derecha con 1rem (column-gap). Con
       el buscador plegado a icono, ese hueco a ambos lados lo dejaba flotando
       lejos del avatar y del resto. En móvil se aprieta la separación. */
    .fi-topbar-end { column-gap: .375rem; min-width: 0; }

    .fi-topbar .fi-global-search-ctn { flex: none; width: 2.25rem; transition: width .2s ease; }

    /* Desplegado NO se le da un ancho calculado: antes era 100vw menos una
       medida a ojo, y cuando no calzaba con el ancho real de la barra el campo
       se montaba encima del avatar. Ahora simplemente se reparte el espacio
       que sobra, así nunca puede pedir más del que hay. */
    .fi-topbar .fi-global-search-ctn:focus-within {
        flex: 1 1 auto;
        width: auto;
        min-width: 0;
    }
    /* Y mientras se escribe, el logo del negocio cede su lugar: es lo único
       prescindible de la barra, y así el campo queda cómodo de verdad. */
    .fi-topbar:has(.fi-global-search-ctn:focus-within) .tb-brand-movil,
    .fi-topbar:has(.fi-global-search-ctn:focus-within) .fi-topbar-start { display: none; }
    .fi-topbar .fi-global-search-field { position: relative; }
    .fi-topbar .fi-global-search-field .fi-sr-only {
        position: absolute; inset: 0; width: auto; height: auto; margin: 0;
        clip: auto; clip-path: none; overflow: visible; white-space: normal;
        text-indent: -9999px; cursor: pointer; z-index: 2;
    }
    .fi-topbar .fi-global-search-ctn:focus-within .fi-sr-only { display: none; }

    /* Plegado, el buscador es un ICONO, no una caja.
       Filament le deja su marco blanco de campo de texto: un cuadrado de 40px
       alrededor de una lupa de 18 se ve enorme y desalineado con los botones
       vecinos, que sí son sólo icono. Mientras está plegado se le quita el
       marco; al enfocarlo vuelve, porque ahí sí es un campo donde se escribe. */
    .fi-topbar .fi-global-search-ctn:not(:focus-within) .fi-input-wrp {
        background: transparent !important;
        box-shadow: none !important;
        border-color: transparent !important;
        min-height: 0;
    }
    /* Plegado ocupa exactamente lo que ocupa un botón de icono de la barra,
       ni un pixel más: antes medía 2,5rem con relleno propio adentro y se veía
       separado de sus vecinos, como si sobrara aire a su alrededor. */
    .fi-topbar .fi-global-search-ctn:not(:focus-within) { width: 2.25rem; }
    .fi-topbar .fi-global-search-ctn:not(:focus-within) .fi-global-search-field,
    .fi-topbar .fi-global-search-ctn:not(:focus-within) .fi-input-wrp,
    .fi-topbar .fi-global-search-ctn:not(:focus-within) .fi-input-wrp-content-ctn {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        height: 2.25rem;
        padding: 0 !important;
        margin: 0 !important;
        gap: 0 !important;
    }
    /* La lupa, del tamaño y color de los demás iconos de la barra. */
    .fi-topbar .fi-global-search-ctn:not(:focus-within) .fi-input-wrp-prefix {
        padding: 0 !important;
        margin: 0 !important;
        flex: none;
    }
    .fi-topbar .fi-global-search-ctn:not(:focus-within) .fi-input-wrp svg {
        width: 1.25rem;
        height: 1.25rem;
    }
    /* Plegado no hay dónde escribir: el campo no debe reservar ancho. */
    .fi-topbar .fi-global-search-ctn:not(:focus-within) .fi-input {
        width: 0 !important;
        min-width: 0 !important;
        padding: 0 !important;
    }
}

/* El avatar se dejaba aplastar cuando la barra iba justa de ancho: en el
   teléfono llegó a medir 13px y se montaba con el botón de tema. */
.fi-topbar .fi-user-menu { flex: none; }

/* Sin logo del negocio no hay a quién cederle el lugar: TapBox va completo. */
.tb-brand--solo img { height: 2.6rem; width: auto; display: block; }
.tb-brand__palabra--grande { font-size: 1.45rem; }
.tb-hero__word { font-family: var(--tb-display); font-weight: 600; font-size: 20px; letter-spacing: -.02em; line-height: 1; }
.tb-hero__word .b { color: #83D1B0; }
.tb-hero__greet { font-family: var(--tb-display); font-weight: 600; font-size: clamp(28px, 4vw, 40px); letter-spacing: -.03em; line-height: 1.05; }
.tb-hero__greet b { color: #83D1B0; font-weight: 600; }
.tb-hero__bottom { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 24px; margin-top: 26px; }
.tb-quickgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(155px, 1fr)); gap: 12px; flex: 1 1 100%; }
.tb-quick { display: inline-flex; align-items: center; justify-content: center; gap: 9px; padding: 13px 16px; border-radius: 12px;
    font-family: var(--tb-display); font-size: 14.5px; font-weight: 500; letter-spacing: -.01em; text-decoration: none; color: #fff;
    background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.14);
    transition: transform .18s ease, background .18s ease, box-shadow .18s ease, border-color .18s ease; }
.tb-quick:hover { background: rgba(112,199,163,.14); border-color: rgba(112,199,163,.55); transform: translateY(-2px); box-shadow: none; color: #C8EAD9; }
.tb-quick:active { transform: translateY(-1px); }
.tb-quick svg { width: 20px; height: 20px; }
.tb-hero__clock { flex: none; margin-left: auto; text-align: right; line-height: 1.15; }
.tb-hero__date { font-family: var(--tb-mono); font-size: 11px; text-transform: capitalize; color: rgba(255,255,255,.9); letter-spacing: .3px; }
.tb-hero__time { font-family: var(--tb-mono); font-size: 15px; font-weight: 500; color: #fff; letter-spacing: .5px; margin-top: 1px; }
@media (max-width: 760px) { .tb-quickgrid { grid-template-columns: 1fr; } }

/* — Texto más nítido (HD) en todo el panel — */
body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; }

/* — Tema claro/oscuro: botón aparte en el topbar; el menú del avatar queda solo con "Cerrar sesión" — */
.fi-dropdown-list:has(.fi-theme-switcher) { display: none !important; }
.tb-theme-trigger { display: inline-flex; align-items: center; justify-content: center; width: 2.25rem; height: 2.25rem; border: 0; background: transparent; border-radius: .5rem; color: #6b7280; cursor: pointer; transition: background .15s, color .15s; margin-inline-end: .25rem; }
.tb-theme-trigger svg { width: 1.3rem; height: 1.3rem; }
.tb-theme-trigger:hover { background: rgba(0,0,0,.05); color: #374151; }
.dark .tb-theme-trigger { color: #a1a1aa; }
.dark .tb-theme-trigger:hover { background: rgba(255,255,255,.08); color: #e4e4e7; }

/* — Reloj (fecha + hora) en la barra superior — */
.tb-clock { display: none; align-items: center; font-family: var(--tb-mono); font-size: 12.5px; letter-spacing: .2px; color: #6b7280; text-transform: capitalize; white-space: nowrap; margin-inline-end: .85rem; }
.dark .tb-clock { color: #a1a1aa; }
@media (min-width: 768px) { .tb-clock { display: inline-flex; } }

/* — Iconos del menú lateral: identidad verde de marca.
     Inactivos en un verde apagado; hover en el verde TapBox; el activo
     conserva el color de marca que aplica Filament. Claro y oscuro. — */
.fi-sidebar-item:not(.fi-active) .fi-sidebar-item-icon { color: #4F7F68 !important; transition: color .15s; }
.fi-sidebar-item:not(.fi-active):hover .fi-sidebar-item-icon { color: #257554 !important; }
.dark .fi-sidebar-item:not(.fi-active) .fi-sidebar-item-icon { color: #7FB49B !important; }
.dark .fi-sidebar-item:not(.fi-active):hover .fi-sidebar-item-icon { color: #83D1B0 !important; }

/* ═══════════════════════════════════════════════════════════════════════
   MODO OSCURO "PRO" — solo .dark
   Estilo iOS: fondo negro real + tarjetas gris elevado (#1c1c1e) + bordes
   neutros sutiles. Jerarquía por elevación, como Ajustes de iPhone.
   ═══════════════════════════════════════════════════════════════════════ */
:root { --tb-d-bg:#000000; --tb-d-surface:#151517; --tb-d-card:#242426; --tb-d-sunken:#2f2f31;
        --tb-d-border:rgba(255,255,255,.09); --tb-d-border-strong:rgba(255,255,255,.15); }

/* Fondo general de la app */
.dark, .dark body, .dark .fi-body { background-color: var(--tb-d-bg) !important; }

/* Barra lateral y superior: un pelo más claras que el fondo + borde frío */
.dark .fi-sidebar { background-color: var(--tb-d-surface) !important; border-inline-end: 1px solid var(--tb-d-border) !important; }
.dark .fi-topbar { background-color: rgba(0,0,0,.8) !important; -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); border-bottom: 1px solid var(--tb-d-border) !important; }

/* Tarjetas / secciones / KPIs / tablas: superficie elevada, borde definido y sombra sutil.
   OJO: el contenedor real de tabla es .fi-ta-ctn (no .fi-ta). */
.dark .fi-section,
.dark .fi-wi-stats-overview-stat,
.dark .fi-ta-ctn { background-color: var(--tb-d-card) !important; }
.dark .fi-section,
.dark .fi-wi-stats-overview-stat,
.dark .fi-ta-ctn {
    border: 1px solid var(--tb-d-border) !important;
    box-shadow: 0 1px 2px rgba(0,0,0,.35), 0 8px 24px -16px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.03) !important;
}

/* Todas las superficies internas de la tabla heredan el color de la tarjeta:
   así no aparecen "manchones" por header/celdas con otro tono. La separación
   del encabezado queda dada por su borde inferior propio de Filament. */
.dark .fi-ta,
.dark .fi-ta-header,
.dark .fi-ta-header-cell,
.dark .fi-ta-row,
.dark .fi-ta-cell,
.dark .fi-ta-header-ctn { background-color: transparent !important; }

/* Campos (inputs, selects, búsqueda, paginación): el color va en el WRAPPER
   redondeado (.fi-input-wrp) y el elemento interno queda transparente. Así el
   fondo respeta las esquinas y no asoman cuadrados. Un borde frío definido los
   delimita en cualquier superficie (incluida la barra superior). */
.dark .fi-input-wrp {
    background-color: var(--tb-d-sunken) !important;
    box-shadow: inset 0 0 0 1px var(--tb-d-border-strong) !important;
}
.dark .fi-input-wrp:has(:focus) {
    box-shadow: inset 0 0 0 1px #257554, 0 0 0 2px rgba(37, 117, 84,.25) !important;
}
.dark .fi-input-wrp:has([aria-invalid="true"]) {
    box-shadow: inset 0 0 0 1px #f87171 !important;   /* conserva el ring de error */
}
.dark .fi-input, .dark .fi-select-input { background-color: transparent !important; }

/* Modales, popovers y dropdowns: misma superficie iOS gris (no el slate/navy
   por defecto de Filament). Cubre las ventanas de "registrar atención", subir
   vacuna/documento, confirmaciones, menús, etc. */
.dark .fi-modal-window,
.dark .fi-dropdown-panel {
    background-color: var(--tb-d-card) !important;
    border: 1px solid var(--tb-d-border) !important;
    box-shadow: 0 24px 60px -12px rgba(0,0,0,.65) !important;
}
.dark .fi-modal-header,
.dark .fi-modal-content,
.dark .fi-modal-footer { background-color: transparent !important; }
/* Secciones/inputs dentro del modal heredan la superficie del propio modal para
   que no aparezca un "card dentro del card" con otro tono. */
.dark .fi-modal-window .fi-section { background-color: transparent !important; box-shadow: none !important; border: 0 !important; }

/* ═══════════════════════════════════════════════════════════════════════
   LOGIN (página simple): SIN card. Contenido directo sobre el fondo (logo,
   TapBox, "Entre a su cuenta", correo*, contraseña*, olvidó, recordarme, entrar).
   ═══════════════════════════════════════════════════════════════════════ */
.fi-simple-main {
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
    padding-inline: 0 !important;
}
.dark .fi-simple-main { background: transparent !important; }

/* Placeholders visibles (ya no hay card que dé contraste). */
.fi-simple-main .fi-input::placeholder { color: #6b7280 !important; opacity: 1; }
.dark .fi-simple-main .fi-input::placeholder { color: #9a9aa0 !important; opacity: 1; }

/* Campos con borde definido sobre el fondo. */
.fi-simple-main .fi-input-wrp {
    background-color: #ffffff !important;
    box-shadow: inset 0 0 0 1px #cbd2dc !important;
}
.dark .fi-simple-main .fi-input-wrp {
    background-color: var(--tb-d-sunken) !important;
    box-shadow: inset 0 0 0 1px var(--tb-d-border-strong) !important;
}

/* Check "Recordarme" con recuadro notorio. */
.fi-simple-main .fi-checkbox-input {
    border: 2px solid #9aa3af !important;
    background-color: #ffffff !important;
}
.dark .fi-simple-main .fi-checkbox-input {
    border: 2px solid #6b7280 !important;
    background-color: transparent !important;
}
.fi-simple-main .fi-checkbox-input:checked {
    background-color: #257554 !important;
    border-color: #257554 !important;
}

/* Todo el contenido del login centrado vertical, sin scroll, adaptable a
   cualquier alto de pantalla (dvh evita el salto por las barras del móvil). */
.fi-simple-layout {
    min-height: 100vh !important;
    min-height: 100dvh !important;
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    justify-content: center !important;
    padding-block: 1.5rem !important;
    padding-inline: 1.75rem !important; /* aire a ambos lados */
}

/* El «sin scroll» es SÓLO para el login.
 *
 * Filament usa esta misma plantilla simple para el PERFIL, que es mucho más
 * largo: bloquear el desplazamiento ahí dejaba el bloque de verificación en
 * dos pasos fuera de alcance, sin forma de llegar a él.
 *
 * Se distinguen por el menú de usuario: el perfil lo tiene (hay sesión
 * iniciada), el login no. El perfil además arranca arriba en vez de centrado,
 * porque centrar algo más alto que la pantalla recorta justamente el comienzo.
 */
body:not(:has(.fi-user-menu)) .fi-simple-layout { overflow: hidden !important; }
body:not(:has(.fi-user-menu)):has(.fi-simple-layout) { overflow: hidden; }

body:has(.fi-user-menu) .fi-simple-layout {
    justify-content: flex-start !important;
    overflow-y: auto !important;
}

/*
 * CUANDO LA PANTALLA ES MÁS BAJA QUE EL FORMULARIO.
 *
 * Con la pantalla fija (`html.tb-fija`, ver partials/pantalla-fija) el
 * documento ya no se desplaza, así que el `overflow:hidden` de arriba dejaba
 * el login sin salida: medido en un viewport de 380px de alto, la caja
 * arrancaba en -155px y no había forma de llegar al logo ni al primer campo.
 * Pasa de verdad en un teléfono en horizontal, y sobre todo con el teclado
 * abierto, que es justo lo que esto viene a arreglar.
 *
 * Dos correcciones que van juntas:
 *
 *  · El contenido puede desplazarse POR DENTRO. `contain` corta el rebote en
 *    el borde, así que se sigue sin ver la franja del navegador por detrás.
 *  · Se centra con márgenes automáticas y no sólo con `justify-content`: el
 *    centrado por alineación recorta el COMIENZO cuando el contenido no cabe;
 *    las márgenes automáticas centran igual y ceden cuando falta espacio.
 */
html.tb-fija .fi-simple-layout {
    overflow-y: auto !important;
    overscroll-behavior: contain;
    /*
     * `flex-start` + margen automática, y no `center` a secas.
     *
     * Las márgenes automáticas sólo reparten espacio SOBRANTE: si el contenido
     * es más alto que la pantalla se resuelven en cero, y ahí manda el
     * `justify-content`. Con `center`, ese caso recorta el comienzo —medido:
     * la caja arrancaba en -155px, sin forma de llegar al logo ni al primer
     * campo—. Con `flex-start` de base, la margen automática centra mientras
     * quepa y cede en cuanto deja de caber.
     */
    justify-content: flex-start !important;
}

html.tb-fija .fi-simple-layout > * { margin-block: auto !important; }

/*
 * NADA CAMBIA DE TAMAÑO AL ABRIRSE EL TECLADO.
 *
 * Hubo acá un modo «compacto» que encogía el logo, el título y los espacios
 * cuando el alto útil bajaba: estaba mal. Al tocar un campo, la pantalla se
 * reacomodaba bajo el dedo y la marca se achicaba justo cuando la persona
 * escribe su contraseña — el momento en que ver la marca importa más.
 *
 * En la APK no pasa porque el teclado se DIBUJA ENCIMA: la maqueta conserva su
 * alto y el navegador sólo corre la vista para dejar visible el campo. Es la
 * conducta nativa, y es la que se replica acá midiendo `innerHeight` —el alto
 * de la maqueta— y no `visualViewport`, que es el alto libre y se encoge con
 * el teclado. Ver partials/pantalla-fija.
 */

/* Y el aire entre campos se reparte más justo. */
/*
 * Los espacios entre bloques bajan de 24px a 8-12. Es el recorte que más
 * rinde y el que menos se nota: separar el título de los campos con 24px es
 * una decisión de pantalla grande, no una necesidad de lectura.
 */

/* Botón "Entrar" / "Enviar email": azul de marca (como el Box del logo). */
.fi-simple-main .fi-btn {
    background: #257554 !important;
    border: 0 !important;
    color: #fff !important;
    font-weight: 600 !important;
    letter-spacing: .01em !important;
    border-radius: 0.7rem !important;
    padding-block: 0.8rem !important;
    box-shadow: 0 1px 2px rgba(37, 117, 84,.18) !important;
    transition: background .15s ease, transform .08s ease, box-shadow .15s ease;
}
.fi-simple-main .fi-btn:hover { background: #1C6146 !important; box-shadow: 0 4px 14px -4px rgba(37, 117, 84,.5) !important; }
.fi-simple-main .fi-btn:active { transform: translateY(1px); box-shadow: none !important; }
.dark .fi-simple-main .fi-btn { background: #257554 !important; }
.dark .fi-simple-main .fi-btn:hover { background: #257554 !important; }

/* Notificaciones premium (línea del correo de reset): tarjeta clara/oscura con
   esquinas suaves y sombra cuidada. El acento de color lo da el ícono (azul en
   el aviso de "correo registrado"). */
.fi-no-notification {
    border-radius: 14px !important;
    border: 1px solid #E2E8F0 !important;
    box-shadow: 0 16px 40px -12px rgba(15,26,46,.22) !important;
}
.dark .fi-no-notification {
    background-color: #242426 !important;
    border-color: #2f2f31 !important;
    box-shadow: 0 20px 50px -14px rgba(0,0,0,.6) !important;
}
.fi-no-notification .fi-no-notification-title,
.fi-no-notification h3 { font-weight: 700 !important; letter-spacing: -.01em; }

/* Bloqueo de zoom por gesto (doble-tap) + sin retardo de toque. El pinch-zoom
   lo bloquea el meta viewport; esto complementa en el resto de la app. */
html { touch-action: manipulation; -webkit-text-size-adjust: 100%; }

/* ═══════════════════════════════════════════════════════════════════════
   NITIDEZ "HD" — texto, iconos y detalles (app + central)
   ═══════════════════════════════════════════════════════════════════════ */

/* 1+2) Suavizado de fuentes: texto más limpio y nítido en todo el panel.
   antialiased afina el trazo (menos "gordo") en pantallas Retina/OLED. */
.fi-body, .fi-body *, .fi-sidebar, .fi-topbar, .fi-modal {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

/* 1) Panel lateral: texto e iconos más nítidos y con mejor contraste. */
.fi-sidebar-item-label { font-weight: 500; letter-spacing: -0.005em; }
.dark .fi-sidebar-item-label { color: #eaeaec !important; }
.dark .fi-sidebar-item:not(.fi-active) .fi-sidebar-item-icon { color: #b7bec8 !important; }
.dark .fi-sidebar-group-label { color: #9b9ba1 !important; letter-spacing: .02em; }
/* SVG de iconos con render de máxima precisión (bordes limpios). */
.fi-sidebar-item-icon svg,
.fi-btn svg,
.fi-ta-actions svg { shape-rendering: geometricPrecision; }

/* 2) Encabezados y textos generales: contraste alto en oscuro. */
.dark .fi-header-heading,
.dark .fi-section-heading,
.dark .fi-ta-header-heading { color: #f5f5f7 !important; }
.dark .fi-ta-text, .dark .fi-ta-cell, .dark .fi-in-text { color: #e4e4e7; }

/* 3) REDONDEO GLOBAL de todos los cards (todas las plantillas, app + central):
   KPIs, secciones, tablas y widgets. El tile de KPI (fi-wi-stats-overview-stat)
   es el que salía con esquinas en punta. */
.fi-wi-stats-overview-stat,
.fi-section,
.fi-ta-ctn,
.fi-wi > .fi-section,
.fi-fo-tabs {
    border-radius: 0.9rem !important;
}
.fi-wi-stats-overview-stat { overflow: hidden; }

/* 4) Fecha/hora, placeholders y buscadores: texto nítido y placeholder legible. */
.dark .fi-input,
.dark .fi-select-input { color: #f2f2f7 !important; }
.dark .fi-input::placeholder,
.dark .fi-select-input::placeholder { color: #8a8a8e !important; opacity: 1; }
.dark .fi-ta-search-field .fi-input { color: #f2f2f7 !important; }

/* Conmutador de tema flotante en el login (sin topbar). Oculto por defecto;
   solo aparece en las páginas simples (login) de cualquier panel. */
.tb-login-theme { display: none; }
body:has(.fi-simple-layout) .tb-login-theme,
body:has(.fi-simple-page) .tb-login-theme,
body:has(.fi-simple-main) .tb-login-theme {
    display: block; position: fixed; top: 1rem; inset-inline-end: 1rem; z-index: 50;
}

/* Perfil también es una página simple, pero AHÍ SÍ hay avatar de usuario, y
   Filament lo fija arriba a la derecha: el conmutador flotante caía justo
   encima y los dos círculos se pisaban. Cuando conviven, el tema se corre a la
   izquierda del avatar y queda una separación real entre ambos.
      avatar: 2rem de ancho + 1rem de margen al borde, más 0.5rem de aire y el
      0.25rem que el propio botón lleva de margen a la derecha. */
body:has(.fi-simple-page):has(.fi-user-menu) .tb-login-theme,
body:has(.fi-simple-main):has(.fi-user-menu) .tb-login-theme {
    inset-inline-end: 4.25rem;
}

/* Flecha "Volver" del Perfil: arriba a la izquierda, en el mismo tono discreto
   que el resto de los controles de la barra. */
.tb-profile-back { position: fixed; top: 1rem; inset-inline-start: 1rem; z-index: 50; }
.tb-profile-back button {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .4rem .7rem .4rem .5rem; border: 0; border-radius: .5rem;
    background: transparent; color: #6b7280; cursor: pointer;
    font: inherit; font-size: .875rem; transition: background .15s, color .15s;
}
.tb-profile-back svg { width: 1.15rem; height: 1.15rem; }
.tb-profile-back button:hover { background: rgba(0,0,0,.05); color: #374151; }
.dark .tb-profile-back button { color: #a1a1aa; }
.dark .tb-profile-back button:hover { background: rgba(255,255,255,.08); color: #e4e4e7; }

/* En el topbar el avatar y el conmutador quedaban pegados, sin un pixel entre
   ellos: el fondo del botón de tema al pasar el mouse tocaba el borde del
   círculo de iniciales. */
.fi-topbar .fi-user-menu { margin-inline-end: .5rem; }

/* ═══════════════════════════════════════════════════════════════════════
   FICHAS COMPACTAS (estilo CRM/B2B). Solo secciones marcadas con .tb-crm
   (p. ej. ficha de cliente). No afecta al resto de formularios.
   ═══════════════════════════════════════════════════════════════════════ */
/* Medido sobre el DOM real antes de tocar nada: cabecera 14×20, contenido
   18×20, título 16px, etiquetas 14px, separación entre tarjetas 24px. Todo
   generoso; se veía espacioso y de plantilla. Acá se aprieta y se le da
   jerarquía. */

/* — Tarjeta — */
.tb-crm .fi-section {
    border-radius: 12px !important;
    box-shadow: 0 1px 2px rgba(16, 24, 40, .04) !important;
}
.dark .tb-crm .fi-section { box-shadow: none !important; }

/* — Cabecera: más baja, con una línea que la separa del contenido — */
.tb-crm .fi-section-header {
    padding: .7rem .95rem !important;
    border-bottom: 1px solid rgba(16, 24, 40, .07);
    gap: .55rem !important;
}
.dark .tb-crm .fi-section-header { border-bottom-color: rgba(255, 255, 255, .07); }

/* Título de sección: etiqueta, no encabezado de página. */
.tb-crm .fi-section-header-heading {
    font-size: .875rem !important;
    font-weight: 600 !important;
    letter-spacing: -.01em;
}
.tb-crm .fi-section-header-description { font-size: .75rem !important; margin-top: .1rem; }

/* El icono va en una pastilla verde: da identidad y ancla la vista. */
.tb-crm .fi-section-header > svg {
    width: 1.85rem !important;
    height: 1.85rem !important;
    padding: .35rem;
    border-radius: 8px;
    color: #257554;
    background: #E8F5EF;
    box-sizing: border-box;
    flex: none;
}
.dark .tb-crm .fi-section-header > svg {
    color: #83D1B0;
    background: rgba(112, 199, 163, .12);
}

/* — Contenido: menos aire — */
.tb-crm .fi-section-content { padding: .85rem .95rem !important; }
.tb-crm .fi-grid { gap: .6rem .8rem !important; }
.tb-crm .fi-fo-field-wrp { gap: .3rem !important; }

/* — Etiquetas de campo: pequeñas y apagadas; el dato es el protagonista — */
.tb-crm .fi-fo-field-label-content {
    font-size: .75rem !important;
    font-weight: 500 !important;
    letter-spacing: .01em;
    color: rgb(100 116 139);
}
.dark .tb-crm .fi-fo-field-label-content { color: rgb(148 163 184); }

/* — Campos — */
.tb-crm .fi-input-wrp { border-radius: 9px !important; }
.tb-crm .fi-input,
.tb-crm .fi-select-input { padding-block: .35rem !important; font-size: .8125rem !important; }
.tb-crm .fi-fo-field-hint,
.tb-crm .fi-fo-field-helper-text { font-size: .7rem !important; }

/* Foco en verde de marca, en vez del azul del navegador. */
.tb-crm .fi-input-wrp:focus-within {
    outline: 2px solid rgba(37, 117, 84, .35);
    outline-offset: 1px;
}

/* — Separación entre tarjetas apiladas: 24px era demasiado — */
.fi-fo .fi-sc > .fi-sc-component + .fi-sc-component,
.fi-sc-has-gap { gap: .85rem !important; }

/* — Barra de acciones fija abajo: los botones quedan siempre a mano y la
     página deja de terminar en un vacío enorme. — */
.fi-fo-actions-ctn,
.fi-page-content > form > .fi-ac {
    position: sticky;
    bottom: 0;
    z-index: 10;
    margin-top: 1rem;
    padding: .75rem 0;
    background: linear-gradient(to top, var(--tb-page-bg, #f8fafc) 72%, transparent);
}
.dark .fi-fo-actions-ctn,
.dark .fi-page-content > form > .fi-ac {
    background: linear-gradient(to top, #000 72%, transparent);
}

/* ═══════════════════════════════════════════════════════════════════════
   QUOTE BUILDER (Central → Crear/Editar cotización) · 3 columnas compactas
   ═══════════════════════════════════════════════════════════════════════ */
/* Contenedor: ancho amplio pero acotado y centrado (nada pegado a la izq.) */
.tb-qb { max-width: 1600px; margin-inline: auto; width: 100%; gap: 1rem !important; }
/* Barra lateral sticky */
@media (min-width: 1024px) { .tb-sticky { position: sticky; top: 1rem; } }

/* Cards compactas del builder */
.tb-qb-card .fi-section-content { padding: 15px 16px !important; }
.tb-qb-card .fi-section-header { padding: 13px 16px !important; }
.tb-qb .fi-grid { gap: .55rem .7rem !important; }
/* Inputs 34–38px y labels chicos */
.tb-qb .fi-input, .tb-qb .fi-select-input { padding-block: .4rem !important; }
.tb-qb .fi-fo-field-label-content { font-size: .8rem !important; }

/* Resumen ejecutivo (derecha) */
.tb-quote-sum { margin-top: 2px; }
.tb-quote-sum__div { border-top: 1px dashed #e5e7eb; margin: 8px 0; }
.dark .tb-quote-sum__div { border-color: var(--tb-d-border); }
.tb-quote-sum__total {
    display: flex; justify-content: space-between; align-items: baseline;
    margin-top: 12px; padding: 14px 16px; border-radius: 12px;
    background: #eaf2fd; color: #20282D;
}
.dark .tb-quote-sum__total { background: rgba(37, 117, 84,.16); color: #f5f5f7; }
.tb-quote-sum__total span:first-child { font-size: 13px; font-weight: 600; color: #257554; }
.dark .tb-quote-sum__total span:first-child { color: #83D1B0; }
.tb-quote-sum__total span:last-child { font-size: 22px; font-weight: 800; letter-spacing: -.5px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tb-quote-sum > div { white-space: nowrap; }
.tb-quote-sum > div > span:first-child { white-space: normal; }

/* Módulos como tarjetas compactas (~90px), grilla 2 col */
.tb-modules .fi-fo-checkbox-list-option,
.tb-modules label:has(> input[type="checkbox"]) {
    border: 1px solid #e5e7eb; border-radius: 12px; padding: 12px 14px; min-height: 88px;
    transition: border-color .12s, background .12s, box-shadow .12s; cursor: pointer;
}
.dark .tb-modules .fi-fo-checkbox-list-option,
.dark .tb-modules label:has(> input[type="checkbox"]) { border-color: var(--tb-d-border); background: var(--tb-d-card); }
.tb-modules .fi-fo-checkbox-list-option:hover,
.tb-modules label:has(> input[type="checkbox"]):hover { border-color: #257554; box-shadow: 0 2px 12px -6px rgba(37, 117, 84,.5); }
.tb-modules .fi-fo-checkbox-list-option:has(:checked),
.tb-modules label:has(> input[type="checkbox"]:checked) { border-color: #257554; background: #eaf2fd; }
.dark .tb-modules .fi-fo-checkbox-list-option:has(:checked),
.dark .tb-modules label:has(> input[type="checkbox"]:checked) { background: rgba(37, 117, 84,.16); border-color: #257554; }
.tb-modules .fi-fo-checkbox-list { gap: .55rem !important; }

/* ── Cabecera de identidad (ficha de cliente/paciente) ── */
.tb-idcard {
    display: flex; align-items: center; gap: 16px;
    padding: 16px 20px; border-radius: 0.9rem;
    background: #ffffff; border: 1px solid #e5e7eb;
    box-shadow: 0 1px 2px rgba(15,26,46,.05);
}
.dark .tb-idcard { background: var(--tb-d-card); border-color: var(--tb-d-border);
    box-shadow: 0 1px 2px rgba(0,0,0,.35), 0 8px 24px -16px rgba(0,0,0,.6); }
.tb-idcard__avatar {
    flex: none; width: 52px; height: 52px; border-radius: 13px;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 18px; letter-spacing: .3px;
    background: #e8f0fe; color: #257554;
}
.dark .tb-idcard__avatar { background: rgba(37, 117, 84,.18); color: #83D1B0; }
.tb-idcard__main { min-width: 0; }
.tb-idcard__name { font-size: 19px; font-weight: 700; line-height: 1.15; color: #20282D; }
.dark .tb-idcard__name { color: #f5f5f7; }
.tb-idcard__meta { margin-top: 3px; font-size: 13px; color: #64748b; }
.dark .tb-idcard__meta { color: #9aa0aa; }
.tb-idcard__badge {
    margin-inline-start: auto; flex: none;
    display: inline-flex; align-items: center; gap: 7px;
    padding: 6px 14px; border-radius: 999px;
    font-size: 13px; font-weight: 600;
    color: #16a34a; background: rgba(22,163,74,.10); border: 1px solid rgba(22,163,74,.25);
}
.dark .tb-idcard__badge { color: #4ade80; }
.tb-idcard__badge::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
/* Avatar con foto (ficha de mascota) */
.tb-idcard__avatar--img { padding: 0; overflow: hidden; background: #e8f0fe; }
.tb-idcard__avatar--img img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Badge de dueño (azul, sin punto) */
.tb-idcard__badge--owner { color: #257554; background: rgba(37, 117, 84,.10); border-color: rgba(37, 117, 84,.25); }
.dark .tb-idcard__badge--owner { color: #83D1B0; }
.tb-idcard__badge--owner::before { display: none; }

/* ── Botón escribir tarjeta NFC ── */
.tb-nfc__btn {
    display: inline-flex; align-items: center; gap: 8px;
    background: #257554; color: #fff; border: 0; border-radius: 10px;
    padding: 10px 16px; font-weight: 700; font-size: 14px; cursor: pointer;
}
.tb-nfc__btn:disabled { opacity: .6; cursor: progress; }
.tb-nfc__btn:hover:not(:disabled) { background: #1C6146; }
.tb-nfc__status { margin-top: 8px; font-size: 13px; color: #94a3b8; }
.tb-nfc__status.is-ok { color: #16a34a; font-weight: 600; }
.tb-nfc__hint { font-size: 13px; color: #94a3b8; }

/* ═══════════════════════════════════════════════════════════════════════
   APP INSTALADA (TWA/PWA): sin "tap-to-search" ni menú de selección de Chrome
   en textos no editables. Solo aplica en modo standalone (no en el navegador).
   ═══════════════════════════════════════════════════════════════════════ */
@media (display-mode: standalone) {
    body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
    input, textarea, select, [contenteditable="true"],
    .fi-input, .fi-select-input { -webkit-user-select: text !important; user-select: text !important; }
}

/* ═══════════════════════════════════════════════════════════════════════
   RESPONSIVE (móvil / tablet / iPad) · App + Central
   ═══════════════════════════════════════════════════════════════════════ */
/* Ningún card debe provocar scroll horizontal del cuerpo */
.fi-section, .tb-idcard, .tb-hero, .tb-qb, .tb-qb-card { max-width: 100%; }

/* Tablet e inferior (≤ 1024px, incluye iPad) */
@media (max-width: 1024px) {
    .tb-hero { padding: 22px 22px; }
    .tb-hero__bottom { gap: 18px; margin-top: 20px; }
    /* Quote builder: todo apilado a una columna, resumen debajo */
    .tb-sticky { position: static !important; }
}

/* Móvil / tablet chico (≤ 768px) */
@media (max-width: 768px) {
    .tb-hero { padding: 18px 16px; border-radius: 14px; }
    .tb-quickgrid { grid-template-columns: repeat(2, 1fr); flex-basis: 100%; }
    .tb-idcard { flex-wrap: wrap; padding: 14px 16px; gap: 12px; }
    .tb-idcard__badge { margin-inline-start: 0; }
    .tb-qb-card .fi-section-content { padding: 13px 14px !important; }
    /* Inputs cómodos al tacto (evita zoom en iOS con < 16px) */
    .fi-input, .fi-select-input { font-size: 16px !important; }
}

/* Teléfono (≤ 480px) */
@media (max-width: 480px) {
    .tb-quickgrid { grid-template-columns: 1fr; }
    .tb-hero__greet { font-size: 26px; }
    .tb-idcard__avatar { width: 46px; height: 46px; font-size: 16px; }
    .tb-idcard__name { font-size: 17px; }
}

/* — Marca del panel: "Tap" en tinta, "Box" en verde —
   El tono del "Box" cambia según el fondo: sobre claro necesita el verde
   oscuro (#257554 da 5.6 de contraste); sobre el tema oscuro, el aclarado. */
.tb-marca { display: inline-flex; align-items: center; gap: 9px; }
.tb-marca__ic { height: 1.6rem; width: auto; display: block; }
.tb-marca__tx {
    font-family: var(--tb-display, 'Schibsted Grotesk', Inter, sans-serif);
    font-weight: 700; font-size: 1.06rem; letter-spacing: -.02em; line-height: 1;
    color: #20282D; white-space: nowrap;
}
.tb-marca__b { color: #257554; }
.tb-marca__sub { font-weight: 500; opacity: .55; letter-spacing: -.01em; }

.dark .tb-marca__tx { color: #F6F7F5; }
.dark .tb-marca__b { color: #83D1B0; }

/* — El "Box" del logotipo del panel —
   Sobre fondo claro necesita el verde oscuro (5.6 de contraste); sobre el tema
   oscuro, el aclarado. Va por clase y no como color fijo en línea para que
   pueda cambiar con el tema.
   El !important es deliberado: Filament pinta la marca con currentColor
   heredado de la barra, y sin esto el "Box" sale negro en ambos temas. */
.tb-box,
.fi-topbar .tb-box,
.fi-sidebar .tb-box { color: #257554 !important; }

.dark .tb-box,
.dark .fi-topbar .tb-box,
.dark .fi-sidebar .tb-box { color: #83D1B0 !important; }
/* ══════════════════════════════════════════════════════════════════════
   SÓLO ESCRITORIO (≥768px)
   Todo lo que sigue existe para una sola cosa: que en una FILA de formulario
   el desplegable, el campo de texto y el selector de fecha midan igual y su
   texto quede a la misma altura. En móvil no hay filas — cada campo va a
   ancho completo, uno debajo del otro — así que nada de esto hace falta ahí.
   Y sí hace daño: el desplegable no nativo dibuja su PANEL DE OPCIONES dentro
   de la misma caja, así que cualquier altura o ancho impuesto lo aplasta. Eso
   descuadró «Existencias» de Inventario en el teléfono cuatro veces seguidas
   («otro» partido letra por letra, etiquetas encabalgadas).
   Si vuelve a aparecer un descuadre de formulario SÓLO en móvil, la causa
   está acá adentro y la respuesta es acotar, no agregar otra regla.
   ══════════════════════════════════════════════════════════════════════ */
@media (min-width: 768px) {

/* — Formularios: campos parejos y sin texto cortado —
   Los desplegables de Filament traen su propio control y quedaban más altos
   que los campos de texto de al lado, con la fila desalineada. Y cuando el
   campo era angosto, el valor se partía en dos líneas o se recortaba.

   OJO: la clase del contenedor de campo es .fi-fo-field, NO .fi-fo-field-wrp.
   Una versión anterior de este bloque usaba -wrp y por eso no hacía nada:
   verificado midiendo el DOM real (select 50px, texto 38px, fecha 36px). */
.fi-fo-field .fi-input-wrp { min-height: 2.625rem; }

/* Altura fija e idéntica para los tres controles que conviven en una fila. */
.fi-fo-field .fi-input-wrp.fi-fo-select,
.fi-fo-field .fi-input-wrp.fi-fo-text-input,
.fi-fo-field .fi-input-wrp.fi-fo-date-time-picker { height: 2.625rem; }

/* EXCEPCIÓN · desplegables de selección múltiple.
   La regla de arriba emparejó las filas del formulario de citas, pero le impuso
   altura fija a TODOS los desplegables. Uno de selección múltiple pinta un
   distintivo por cada valor elegido y necesita crecer: con 13 módulos, la
   segunda fila de distintivos se salía de la caja y tapaba el texto de ayuda.
   Se reconocen por el contenedor de distintivos que Filament sólo usa ahí. */
.fi-fo-field .fi-input-wrp.fi-fo-select:has(.fi-select-input-value-badges-ctn) {
    height: auto;
    min-height: 2.625rem;
}
/* Los distintivos fluyen en varias líneas, con aire entre ellos. */
.fi-fo-field .fi-select-input-value-badges-ctn {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    padding-block: .35rem;
    min-width: 0;
}
/* Un valor largo no debe empujar la caja a lo ancho ni cortarse a la mitad. */
.fi-fo-field .fi-select-input-value-badges-ctn > * { max-width: 100%; }
/* El control interno de un múltiple tampoco se estira a una altura fija. */
.fi-fo-field .fi-fo-select:has(.fi-select-input-value-badges-ctn) > *,
.fi-fo-field .fi-fo-select:has(.fi-select-input-value-badges-ctn) button {
    height: auto;
    min-height: 2.625rem;
}

/* El control interno estira hasta la caja en vez de imponer su propia altura.
 *
 * CUIDADO CON `.fi-select-input`: en el desplegable NO NATIVO esa clase NO está
 * en el control, sino en el <div> contenedor donde el JavaScript de Filament
 * dibuja el widget completo — el PANEL DE OPCIONES incluido (ver
 * vendor/filament/forms/.../select.blade.php, línea 216). Darle `height:100%`
 * lo mete entero dentro de 2,6 rem: la lista queda aplastada, las etiquetas se
 * encabalgan y una opción como «Otro…» se parte letra por letra en vertical.
 * Se vio al editar una unidad en Inventario, y se confirmó volcando el DOM real.
 *
 * Por eso: el <select> NATIVO por su etiqueta, y del no nativo sólo el BOTÓN.
 * Ni `> *`, ni `.fi-select-input` a secas, ni `> button` (no es hijo directo). */
.fi-fo-field .fi-fo-select select.fi-select-input,
.fi-fo-field .fi-fo-select .fi-select-input-btn,
.fi-fo-field .fi-input-wrp input { height: 100%; }

/* El panel de opciones se dimensiona solo, pase lo que pase arriba.
   Va con !important porque más abajo hubo (y podría volver a haber) reglas que
   intentan darle altura fija a este contenedor: es el error que descuadró
   «Existencias» en Inventario tres veces seguidas. */
.fi-fo-field .fi-fo-select .fi-select-input:not(select) {
    height: auto !important;
    min-height: 0 !important;
    display: block !important;
}
.fi-fo-field .fi-fo-select [role="listbox"],
.fi-fo-field .fi-fo-select [role="option"] { height: auto; white-space: normal; }

/* El valor va en una línea: si no cabe, se corta con puntos suspensivos en
   vez de romperse en dos renglones y descuadrar la fila. */
.fi-fo-field .fi-fo-select [class*="selected"]:not([role="option"]),
.fi-fo-field .fi-fo-select .fi-fo-select-value,
.fi-fo-field .fi-fo-select > button > span,
.fi-fo-field .fi-fo-select select {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
} /* fin · sólo escritorio */

/* ═══════════════════════════════════════════════════════════════════════
   SELECTOR DE EMPRESA DEL STAFF (topbar de /app)
   Solo lo ve el staff de TapBox. Deja claro a qué empresa está mirando.
   ═══════════════════════════════════════════════════════════════════════ */
.tb-switch {
    display: flex; align-items: center; gap: .4rem;
    margin-inline-end: .75rem;
}
.tb-switch__lbl {
    font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
    color: rgb(107 114 128); white-space: nowrap;
}
.dark .tb-switch__lbl { color: rgb(148 163 184); }

.tb-switch__sel {
    height: 2rem; max-width: 12rem; padding: 0 1.6rem 0 .6rem;
    font-size: .8125rem; border-radius: .5rem;
    border: 1px solid rgb(209 213 219); background-color: #fff; color: rgb(17 24 39);
}
.dark .tb-switch__sel {
    border-color: rgb(255 255 255 / .12); background-color: rgb(255 255 255 / .05); color: rgb(226 232 240);
}

.tb-switch__btn {
    height: 2rem; padding: 0 .7rem; border-radius: .5rem; border: 0;
    font-size: .8125rem; font-weight: 600; cursor: pointer;
    background-color: #257554; color: #fff;
}
.tb-switch__btn:hover { background-color: #1C6146; }

/* En pantallas chicas el topbar no alcanza: se deja solo el desplegable. */
@media (max-width: 640px) {
    .tb-switch__lbl { display: none; }
    .tb-switch__sel { max-width: 8rem; }
}

/* ═══════════════════════════════════════════════════════════════════════
   CAMPO DE ETIQUETAS (teléfonos del cliente)
   El placeholder se veía descolgado respecto a la caja: el input vive dentro
   de un contenedor flex junto a las etiquetas ya ingresadas, y sin altura ni
   alineación propias quedaba pegado arriba.
   ═══════════════════════════════════════════════════════════════════════ */
/* OJO CON EL SELECTOR: `.fi-fo-tags-input .fi-input-wrp` no existe. Las dos
   clases van en EL MISMO elemento (`.fi-input-wrp.fi-fo-tags-input`), así que
   esa regla —escrita como descendiente— nunca hizo nada. Medido: el input
   quedaba de 17px pegado al borde de arriba de una caja de 42, con 25px de
   vacío debajo. Es lo que hacía ver el texto de ejemplo «colgado». */
.fi-fo-field .fi-input-wrp.fi-fo-tags-input { align-items: center; }

/* El contenedor intermedio tampoco centra por su cuenta. */
.fi-fo-field .fi-input-wrp.fi-fo-tags-input > .fi-input-wrp-content-ctn {
    display: flex;
    align-items: center;
    min-width: 0;
}
.fi-fo-field .fi-input-wrp.fi-fo-tags-input > .fi-input-wrp-content-ctn > * {
    flex: 1 1 auto;
    min-width: 0;
}

/* Y el input recupera su alto natural: la regla de los desplegables le daba
   `height: 100%` sobre un padre de alto automático, que resuelve en la altura
   del texto y lo deja apoyado arriba. */
.fi-fo-field .fi-input-wrp.fi-fo-tags-input input {
    height: auto;
    line-height: 1.5;
    padding-block: 0;
}

/* El placeholder hereda la línea del input, no la del contenedor. */
.fi-fo-field .fi-input-wrp.fi-fo-tags-input input::placeholder { line-height: inherit; opacity: .55; }

/* ═══════════════════════════════════════════════════════════════════════
   HISTORIAL DE LA MASCOTA · línea de tiempo (agenda + atenciones + vacunas)
   Colores por variable para que el modo oscuro se resuelva solo.
   ═══════════════════════════════════════════════════════════════════════ */
.tb-hist { display: flex; flex-direction: column; gap: .85rem; }

.tb-hist__item { position: relative; display: flex; gap: .7rem; padding-left: .1rem; }
/* Línea vertical que une los hitos; el último no la lleva. */
.tb-hist__item::before {
    content: ""; position: absolute; left: .3rem; top: 1.1rem; bottom: -.85rem;
    width: 1px; background: rgb(0 0 0 / .1);
}
.dark .tb-hist__item::before { background: rgb(255 255 255 / .12); }
.tb-hist__item:last-child::before { display: none; }

.tb-hist__punto {
    flex: none; width: .65rem; height: .65rem; margin-top: .3rem;
    border-radius: 999px; background: #257554; position: relative; z-index: 1;
    box-shadow: 0 0 0 3px rgb(37 117 84 / .14);
}
.tb-hist__item--vacuna .tb-hist__punto { background: #70C7A3; box-shadow: 0 0 0 3px rgb(112 199 163 / .16); }
.tb-hist__item--cita .tb-hist__punto { background: #4F7F68; box-shadow: 0 0 0 3px rgb(79 127 104 / .16); }

.tb-hist__cuerpo { flex: 1; min-width: 0; }
.tb-hist__cab { display: flex; align-items: center; gap: .45rem; flex-wrap: wrap; }
.tb-hist__fecha { font-family: var(--tb-mono); font-size: .7rem; color: rgb(107 114 128); }
.dark .tb-hist__fecha { color: rgb(148 163 184); }
.tb-hist__tipo {
    font-size: .65rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 700;
    color: #1C6146; background: #E8F5EF; padding: .1rem .4rem; border-radius: 999px;
}
.dark .tb-hist__tipo { color: #83D1B0; background: rgb(112 199 163 / .14); }
.tb-hist__estado { font-size: .65rem; color: rgb(107 114 128); text-transform: capitalize; }
.dark .tb-hist__estado { color: rgb(148 163 184); }

.tb-hist__titulo { font-size: .85rem; font-weight: 600; margin: .15rem 0 0; }
.tb-hist__detalle, .tb-hist__pie { font-size: .78rem; color: rgb(107 114 128); margin: .1rem 0 0; }
.dark .tb-hist__detalle, .dark .tb-hist__pie { color: rgb(148 163 184); }

.tb-hist__vacio { font-size: .82rem; color: rgb(107 114 128); }
.dark .tb-hist__vacio { color: rgb(148 163 184); }

/* ══════════════════════════════════════════════════════════════════════
   SÓLO ESCRITORIO (≥768px)
   Todo lo que sigue existe para una sola cosa: que en una FILA de formulario
   el desplegable, el campo de texto y el selector de fecha midan igual y su
   texto quede a la misma altura. En móvil no hay filas — cada campo va a
   ancho completo, uno debajo del otro — así que nada de esto hace falta ahí.
   Y sí hace daño: el desplegable no nativo dibuja su PANEL DE OPCIONES dentro
   de la misma caja, así que cualquier altura o ancho impuesto lo aplasta. Eso
   descuadró «Existencias» de Inventario en el teléfono cuatro veces seguidas
   («otro» partido letra por letra, etiquetas encabalgadas).
   Si vuelve a aparecer un descuadre de formulario SÓLO en móvil, la causa
   está acá adentro y la respuesta es acotar, no agregar otra regla.
   ══════════════════════════════════════════════════════════════════════ */
/* ═══════════════════════════════════════════════════════════════════════
   DESPLEGABLES · EL TEXTO CENTRADO, EN CUALQUIER ANCHO

   Lo que sigue NO impone alturas: sólo centra lo que haya dentro de la caja.
   Por eso puede vivir fuera del bloque de escritorio, donde sí hay reglas de
   altura que en el teléfono rompían la maqueta.

   POR QUÉ IMPORTA: el bloque de escritorio empieza en 768px, así que en un
   modal abierto desde el teléfono —«Asociar vehículo», por ejemplo— el texto
   del desplegable quedaba pegado al borde de arriba. Los campos de una PÁGINA
   no lo mostraban porque Filament ya los centra por su cuenta; los de un modal,
   sí.
   ═══════════════════════════════════════════════════════════════════════ */
.fi-fo-field .fi-fo-select .fi-select-input-btn {
    padding-block: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
}

/* MEDIDO EN EL DOM: el control interno medía 47px dentro de una caja de 42 y
   se desbordaba 5px por abajo. La culpa es de su propio relleno vertical
   (5,6px arriba y abajo) sumado a la altura fija de la caja. Se le quita: la
   caja ya reserva el alto y el centrado lo hace el contenedor. */
.fi-fo-field .fi-fo-select .fi-select-input:not(select) { padding-block: 0; }

/* En los de selección múltiple el relleno se queda: ahí la caja crece con los
   distintivos y ese aire es el que los separa del borde. */
.fi-fo-field .fi-fo-select:has(.fi-select-input-value-badges-ctn) .fi-select-input:not(select) {
    padding-block: .35rem;
}

/* Y el contenedor que sí tiene el alto de la caja centra lo que lleva dentro.
   Sin esto el control se apoyaba arriba y el texto quedaba 3px alto.

   `min-width: 0` EN LA CADENA COMPLETA, y no es opcional: al volver flexible
   este contenedor, sus hijos pasan a tener `min-width: auto`, que les permite
   crecer más que la caja. Con un nombre largo el control se salía por la
   derecha y el valor, la ✕ y la flecha quedaban FUERA del borde. El recorte
   con puntos suspensivos tampoco puede actuar mientras el elemento tenga
   permiso de crecer. */
.fi-fo-field .fi-input-wrp.fi-fo-select > .fi-input-wrp-content-ctn {
    display: flex;
    align-items: center;
    min-width: 0;
}
.fi-fo-field .fi-input-wrp.fi-fo-select > .fi-input-wrp-content-ctn > * {
    flex: 1 1 auto;
    min-width: 0;
    max-width: 100%;
}

/* EL VALOR ELEGIDO VA EN UNA LÍNEA, EN CUALQUIER ANCHO.

   «Andrea Hernández Contreras» en un desplegable de teléfono se partía en
   TRES renglones y el último quedaba cortado por el borde de la caja. Se corta
   con puntos suspensivos, que es lo que hace cualquier campo de una ficha.

   Esta regla vivía sólo en el bloque de escritorio; en el teléfono, que es
   donde el ancho aprieta, no aplicaba.

   Se excluyen los de selección MÚLTIPLE: ahí el primer hijo es el contenedor
   de distintivos y tiene que poder fluir en varias líneas. */
.fi-fo-field .fi-fo-select:not(:has(.fi-select-input-value-badges-ctn)) .fi-select-input-btn > *:first-child {
    flex: 1 1 auto;
    min-width: 0;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* `display: block` es lo que hace visibles los puntos suspensivos:
       Filament trae este contenedor en `flex`, y `text-overflow` no actúa
       sobre el texto suelto de una caja flexible. Sin esto el nombre se
       cortaba en seco contra la flecha, sin señal de que seguía. */
    display: block;
    line-height: 1.4;
}

/* Los dos contenedores intermedios tampoco centran por su cuenta: mientras
   ellos no se estiren a lo alto, el botón se apoya arriba. */
.fi-fo-field .fi-fo-select .fi-select-input > div:has(.fi-select-input-ctn),
.fi-fo-field .fi-fo-select .fi-select-input-ctn {
    display: flex;
    align-items: center;
    min-width: 0;
}

/* Y el botón tampoco: es el último eslabón antes del texto. */
.fi-fo-field .fi-fo-select .fi-select-input-btn { min-width: 0; max-width: 100%; }

/* En los de selección múltiple mandan los distintivos: la caja crece con ellos
   y el contenido se apoya arriba, que es lo correcto ahí. */
.fi-fo-field .fi-fo-select:has(.fi-select-input-value-badges-ctn) .fi-select-input > div:has(.fi-select-input-ctn),
.fi-fo-field .fi-fo-select:has(.fi-select-input-value-badges-ctn) .fi-select-input-ctn {
    align-items: flex-start;
}

@media (min-width: 768px) {
/* ═══════════════════════════════════════════════════════════════════════
   DESPLEGABLES · el texto tiene que quedar centrado en su caja
   Medido en el DOM: el control interno del select medía 60px dentro de una
   caja de 42, corrido 29px hacia abajo. Por eso el texto de ejemplo se veía
   "chueco" respecto a los campos de texto vecinos, que estaban perfectos.
   ═══════════════════════════════════════════════════════════════════════ */
.fi-fo-field .fi-fo-select .fi-select-input-btn {
    height: 100% !important;
    min-height: 0 !important;
    padding-block: 0 !important;
    display: flex;
    align-items: center;
    /* OJO: sin esto el botón se encoge al ancho de su texto (medido: 194px
       dentro de una caja de 327) y el valor con su flecha quedan agrupados a
       la izquierda, con el resto de la caja vacío. Se ve torcido.
       Con width:100% NO basta: el botón es un elemento flexible dentro de la
       caja, así que hay que decirle que CREZCA (flex-grow), no cuánto mide. */
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
    justify-content: space-between;
    gap: .5rem;
}
/* Entre la caja y el botón hay dos contenedores intermedios que NO crecen —
   ni a lo ancho (medido: 194px dentro de 327) ni a lo alto (36 y 17px dentro
   de 42). Mientras ellos no se estiren, el botón no puede: su width:100% y su
   height:100% se calculan sobre esos contenedores encogidos, y el texto queda
   descentrado hacia arriba. */
.fi-fo-field .fi-fo-select .fi-select-input > div:has(.fi-select-input-ctn),
.fi-fo-field .fi-fo-select .fi-select-input-ctn {
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
    height: 100%;
    display: flex;
    align-items: center;
}

/* En los de selección múltiple los distintivos mandan: ahí NO se fuerza la
   altura, porque la caja tiene que crecer con ellos. */
.fi-fo-field .fi-fo-select:has(.fi-select-input-value-badges-ctn) .fi-select-input > div:has(.fi-select-input-ctn),
.fi-fo-field .fi-fo-select:has(.fi-select-input-value-badges-ctn) .fi-select-input-ctn {
    height: auto;
    align-items: flex-start;
}

/* El texto ocupa el espacio disponible y la flecha se va al extremo. */
.fi-fo-field .fi-fo-select .fi-select-input-btn > *:first-child { flex: 1 1 auto; text-align: left; }
.fi-fo-field .fi-fo-select .fi-select-input-btn > svg,
.fi-fo-field .fi-fo-select .fi-select-input-btn > *:last-child { flex: 0 0 auto; }
/* El valor y el texto de ejemplo comparten la misma línea vertical. */
.fi-fo-field .fi-fo-select .fi-select-input-value-ctn,
.fi-fo-field .fi-fo-select .fi-select-input-value-label,
.fi-fo-field .fi-fo-select .fi-select-input-placeholder {
    display: flex;
    align-items: center;
    /* Probado: forzar height:100% acá lo descuadra 4px. Con alineación al
       centro y el interlineado normal queda a ras (medido: 0px de desviación). */
    line-height: 1.2;
    margin-block: 0;
    min-width: 0;
}
/* Excepción: los de selección múltiple crecen, así que ahí no se fuerza. */
.fi-fo-field .fi-fo-select:has(.fi-select-input-value-badges-ctn) .fi-select-input-btn {
    height: auto !important;
    min-height: 2.625rem !important;
    align-items: flex-start;
}

/* ── Selector de fecha: el mismo problema que los desplegables ──
   Medido: su input mide 29px dentro de una caja de 42 y queda 6,5px por
   sobre el centro, mientras el campo de texto de al lado está a ras.
   Se estiran el disparador y sus contenedores para que el texto quede
   centrado igual que en el resto. */
.fi-fo-field .fi-fo-date-time-picker .fi-fo-date-time-picker-trigger,
.fi-fo-field .fi-fo-date-time-picker .fi-fo-date-time-picker-trigger > div,
.fi-fo-field .fi-fo-date-time-picker .fi-input-wrp-content-ctn > div {
    height: 100%;
    display: flex;
    align-items: center;
}
.fi-fo-field .fi-fo-date-time-picker .fi-fo-date-time-picker-display-text-input {
    height: 100%;
    width: 100%;
    padding-block: 0;
}
} /* fin · sólo escritorio */

/* ═══════════════════════════════════════════════════════════════════════
   CÓDIGO DE 6 DÍGITOS (MFA) · máscara TapBox
   La misma idea del PIN del APK: mientras se escribe, los puntos se van
   convirtiendo en las letras de TapBox — "Tap" en tinta y "Box" en verde.

   CÓMO ESTÁ HECHO POR DENTRO (medido en el CSS de Filament, no supuesto):
     · El contenedor es position:relative y las casillas son INLINE-BLOCK.
       Un primer intento las puso en flex y se apilaron en columna.
     · Los dígitos que se ven NO están en las casillas: son el propio input,
       encima, con un letter-spacing grande. Por eso, además de las letras,
       quedaban los números a la vista.

   Por eso acá: se respeta el flujo inline y se oculta el texto del input —
   la máscara pasa a ser la única señal de avance, igual que en el APK.

   Sin JavaScript: Filament ya marca .fi-active en cada casilla a medida que
   entran dígitos. Si esas clases cambiaran, se pierde el efecto pero el campo
   sigue funcionando: nadie queda fuera por un adorno.
   ═══════════════════════════════════════════════════════════════════════ */
.fi-one-time-code-input-ctn {
    height: 3.25rem !important;
    text-align: center;
    white-space: nowrap;
}

.fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field {
    /* inline-flex, NO flex: así siguen en fila y se centra su contenido. */
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    vertical-align: middle;
    width: 1.75rem !important;
    height: 3.25rem !important;
    margin-inline: .28rem;
    border: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
    font-family: 'Schibsted Grotesk', Inter, system-ui, sans-serif;
    font-weight: 700;
    font-size: 2rem;
    line-height: 1;
}

/* Vacía: solo el punto. */
.fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field::before {
    content: '';
    width: .8rem;
    height: .8rem;
    border-radius: 50%;
    background: #CBD5E1;
}
.dark .fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field::before { background: #3F3F46; }

/* Con dígito: se va el punto y entra la letra. */
.fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field.fi-active::before { display: none; }

.fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field:nth-child(1).fi-active::after { content: 'T'; }
.fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field:nth-child(2).fi-active::after { content: 'a'; }
.fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field:nth-child(3).fi-active::after { content: 'p'; }
.fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field:nth-child(4).fi-active::after { content: 'B'; }
.fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field:nth-child(5).fi-active::after { content: 'o'; }
.fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field:nth-child(6).fi-active::after { content: 'x'; }

/* "Tap" en tinta · "Box" en verde de marca. */
.fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field:nth-child(-n+3).fi-active::after { color: #20282D; }
.fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field:nth-child(n+4).fi-active::after { color: #257554; }
.dark .fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field:nth-child(-n+3).fi-active::after { color: #F4F4F5; }
.dark .fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field:nth-child(n+4).fi-active::after { color: #83D1B0; }

/* El código escrito se oculta: la máscara es la señal de avance, y un código
   de acceso no tiene por qué quedar a la vista de quien mire la pantalla. */
.fi-one-time-code-input {
    color: transparent !important;
    caret-color: transparent !important;
    letter-spacing: normal !important;
}
.fi-one-time-code-input::selection { background: transparent; }

/* En celular: casillas y letras algo más chicas para que quepan sin apretar. */
@media (max-width: 400px) {
    .fi-one-time-code-input-ctn > .fi-one-time-code-input-digit-field {
        width: 1.5rem !important;
        margin-inline: .18rem;
        font-size: 1.75rem;
    }
}

/* ── MFA · "Use un código de recuperación" va DEBAJO del botón ──
   Filament lo pinta como contenido inferior del campo del código, o sea
   dentro del campo y por lo tanto encima del botón de confirmar.

   PRIMER INTENTO, DESCARTADO: aplanar la jerarquía con display:contents para
   poder reordenarlo. Medido, el código y el botón terminaban SOLAPADOS — al
   quitarle la caja a los envoltorios se perdía la altura del campo.

   Lo que sí funciona sin tocar la estructura de Filament: se saca el enlace
   del flujo y se fija al pie del formulario, con espacio reservado abajo para
   que no pise al botón. Si Filament cambiara su marcado, el enlace vuelve a
   su lugar original y sigue funcionando.

   Acotado a #multiFactorChallengeForm: no afecta ningún otro formulario. */
#multiFactorChallengeForm {
    position: relative;
    padding-bottom: 2.4rem;
}
#multiFactorChallengeForm .fi-sc.fi-inline {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    display: flex;
    justify-content: center;
    margin: 0;
}

/* — Tablas en teléfono: una ficha por registro, sin desplazarse de lado —
   La fila ya se resume en un bloque (App\Support\TablaMovil), pero la celda de
   ACCIONES seguía estirando la tabla: cuatro botones en línea no caben en
   375px y devolvían el desplazamiento horizontal.

   POR QUÉ SE DESARMA A BLOQUES Y NO A CAJA FLEXIBLE
   Se intentó con `display:flex` en la fila y quedó peor: un <tr> flexible sale
   de la maquinaria de la tabla, el <tbody> le genera celdas anónimas alrededor
   y el ancho pasa a calcularse sobre una caja fantasma. En pantalla se veía la
   ficha metida en una columna de ~150px con media pantalla en blanco al lado.

   La forma que funciona es desarmar la tabla ENTERA —tabla, cuerpo, fila y
   celdas— a bloques. Un bloque ocupa el ancho de su contenedor por definición,
   así que la ficha usa toda la pantalla y las celdas se apilan solas: primero
   el resumen, después los botones.
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-width: 767px) {
    /* La tabla deja de comportarse como tabla: nada de anchos mínimos ni de
       columnas que negocien espacio entre sí. */
    .fi-ta-table,
    .fi-ta-content table {
        display: block;
        min-width: 0 !important;
        width: 100% !important;
    }
    .fi-ta-content { overflow-x: hidden; }

    .fi-ta-table > thead,
    .fi-ta-table > tbody { display: block; width: 100%; }

    /* La cabecera no aporta nada cuando la fila ya es una ficha: sus títulos
       corresponden a columnas que en el teléfono están ocultas. */
    .fi-ta-table > thead { display: none; }

    .fi-ta-row {
        display: block;
        width: 100%;
        position: relative;
    }

    /* Cada celda visible, una línea a ancho completo.
       Se EXCLUYEN las columnas de escritorio: Filament las esconde con
       `.fi-ta-cell.md\:fi-visible { display:none }` —misma especificidad que
       esta regla, cargada después— y sin excluirlas reaparecían todas en el
       teléfono, entre ellas la ✗ roja del 2FA de Usuarios. El comodín cubre
       cualquier corte (sm/md/lg), no sólo `md`. */
    .fi-ta-row > .fi-ta-cell:not([class*="fi-visible"]):not(.fi-ta-selection-cell) {
        display: block;
        width: 100% !important;
        max-width: 100%;
        min-width: 0;
        white-space: normal;
        padding-block: .35rem;
    }
    /* OJO con `:first-child`: la primera <td> de la fila es la CASILLA DE
       SELECCIÓN, no el texto. Apuntando ahí, el aire de arriba se lo llevaba
       una celda que está posicionada aparte, y la reserva de margen derecho
       también — por eso en Empleados el nombre se metía debajo de la casilla y
       parecía cortado. Se apunta al contenido, excluyéndola. */
    .fi-ta-row > .fi-ta-cell:not(.fi-ta-selection-cell):not([class*="fi-visible"]):nth-of-type(1),
    .fi-ta-row > .fi-ta-selection-cell + .fi-ta-cell { padding-top: .7rem; }
    .fi-ta-row > .fi-ta-cell:last-child { padding-bottom: .7rem; }

    /*
     * EL AIRE VA UNA SOLA VEZ, EN LA CELDA.
     *
     * Filament reparte el respiro de la fila entre la <td> y el envoltorio del
     * contenido: 16px arriba y abajo por dentro. En escritorio se suman en
     * HORIZONTAL —una fila, siete columnas— y no se notan. Acá las celdas se
     * apilan, así que esos 32px se suman en VERTICAL una vez por columna: en
     * Mascotas, con foto, nombre y microchip, la ficha de cada animal quedaba
     * con casi 100px de blanco repartidos en huecos entre líneas que no se
     * entendían.
     *
     * Se anula el de dentro y manda el de la celda, que es el que esta hoja
     * ajusta arriba.
     */
    .fi-ta-row > .fi-ta-cell .fi-ta-text,
    .fi-ta-row > .fi-ta-cell .fi-ta-image,
    .fi-ta-row > .fi-ta-cell .fi-circular,
    .fi-ta-row > .fi-ta-cell .fi-ta-icon,
    .fi-ta-row > .fi-ta-cell > .fi-ta-col > * { padding-block: 0 !important; }

    /*
     * Y todo alineado a la izquierda. Una columna numérica va a la derecha
     * porque en una tabla se compara con la de arriba; apilada no tiene con
     * qué alinearse, y el número se va solo al borde opuesto del nombre —en
     * Mascotas el microchip quedaba flotando lejos del animal al que pertenece.
     */
    .fi-ta-row > .fi-ta-cell,
    .fi-ta-row > .fi-ta-cell .fi-ta-col,
    .fi-ta-row > .fi-ta-cell .fi-ta-text { text-align: left !important; justify-content: flex-start !important; }

    /* La casilla de selección se queda donde siempre: al principio de la
       ficha, a la izquierda. Lo único que hacía falta era que NO heredara el
       ancho completo de las demás celdas — con 341px su caja empezaba fuera
       del margen de la tarjeta y la casilla salía cortada por el borde. */
    .fi-ta-row > .fi-ta-cell.fi-ta-selection-cell {
        display: block;
        width: auto !important;
        padding: .7rem .75rem 0;
    }


    /* EXCEPCIÓN · el menú de tres puntos va al costado, no abajo.
     *
     * Bajar los botones a su propia línea tiene sentido cuando son varios y
     * llevan texto («Documentos», «Ver», «Portal», «Editar»). Cuando la tabla
     * resuelve todo con UN menú de tres puntos —como Consentimientos— esa
     * línea entera se gasta en un icono, y la ficha queda con un renglón
     * suelto debajo del texto.
     *
     * Se reconoce por ser una sola acción y ser un desplegable. Sólo se aplica
     * si la fila no tiene casilla de selección, porque ésa ya ocupa la esquina
     * superior derecha y se estorbarían. */
    .fi-ta-row:not(:has(.fi-ta-selection-cell))
        > .fi-ta-cell:has(.fi-ta-actions .fi-dropdown):not(:has(.fi-ta-actions > *:nth-child(2))) {
        position: absolute;
        inset-inline-end: .5rem;
        /*
         * SE CENTRA ESTIRANDO LA CELDA, NO CON `transform`.
         *
         * `top:50% + translateY(-50%)` centraba igual, pero un elemento con
         * `transform` se convierte en el bloque contenedor de sus descendientes
         * `position: fixed`. El panel del menú de tres puntos es fixed
         * justamente para poder ESCAPAR del contenedor con scroll de la tabla
         * (`.fi-ta-content-ctn`, que va en `overflow: auto`); atrapado por la
         * celda, quedaba anclado a ella y recortado por ese contenedor: en
         * Consentimientos, «Ver comprobante» aparecía detrás de la tarjeta y
         * cortado.
         *
         * Estirar la celda de arriba a abajo y centrar con flex da el mismo
         * resultado visual sin crear ese bloque contenedor.
         */
        top: 0;
        bottom: 0;
        display: flex;
        align-items: center;
        width: auto !important;
        padding: 0;
        z-index: 1;
    }
    /* El texto se detiene antes de llegar al menú. */
    .fi-ta-row:not(:has(.fi-ta-selection-cell)):has(.fi-ta-actions .fi-dropdown)
        > .fi-ta-cell:not(:has(.fi-ta-actions)) { padding-inline-end: 3rem; }

    /* Los botones, en su propia línea y alineados a la izquierda con el texto. */
    .fi-ta-actions {
        flex-wrap: wrap;
        justify-content: flex-start;
        gap: 6px;
        max-width: 100%;
    }
    .fi-ta-actions .fi-btn,
    .fi-ta-actions .fi-icon-btn { flex: none; }

    /* Nada dentro de una celda debe empujar el ancho: ni un RUT ni un correo. */
    .fi-ta-text, .fi-ta-text-item-label { overflow-wrap: anywhere; }
}

/* — Acceso por PIN: estado y acciones —
   El estado va como una tira legible de un vistazo, no como un párrafo. Y las
   dos acciones se separan: «Guardar nuevo PIN» y «Desactivar PIN» pegados —y
   además pegados al campo «Repite el PIN»— invitan a pulsar la equivocada. */
.tb-pin-estado {
    display: flex; align-items: center; gap: 14px;
}
.tb-pin-estado__ic {
    display: inline-flex; align-items: center; justify-content: center;
    width: 42px; height: 42px; border-radius: 12px; flex: none;
    background: rgba(148, 163, 184, .14); color: #64748b;
}
.tb-pin-estado.is-on .tb-pin-estado__ic { background: rgba(37, 117, 84, .12); color: #257554; }
.dark .tb-pin-estado.is-on .tb-pin-estado__ic { background: rgba(131, 209, 176, .14); color: #83D1B0; }

.tb-pin-estado__txt { min-width: 0; flex: 1; }
.tb-pin-estado__tit { font-weight: 700; font-size: 15px; letter-spacing: -.01em; }
.tb-pin-estado__sub { font-size: 13.5px; line-height: 1.55; color: #64748b; margin-top: 2px; }
.dark .tb-pin-estado__sub { color: #94a3b8; }

.tb-pin-estado__chip {
    flex: none; font-size: 11.5px; font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; padding: 5px 11px; border-radius: 999px;
    background: rgba(148, 163, 184, .16); color: #64748b;
}
.tb-pin-estado.is-on .tb-pin-estado__chip { background: rgba(37, 117, 84, .12); color: #257554; }
.dark .tb-pin-estado.is-on .tb-pin-estado__chip { background: rgba(131, 209, 176, .16); color: #83D1B0; }

/* Aire entre el último campo del formulario y los botones. */
.tb-pin-acciones {
    display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
    margin-top: 26px; padding-top: 20px;
    border-top: 1px solid rgb(228 233 231 / 1);
}
.dark .tb-pin-acciones { border-top-color: rgb(255 255 255 / .08); }

/* La acción destructiva se va al otro extremo: no se pulsa por inercia. */
.tb-pin-acciones > *:last-child:not(:first-child) { margin-inline-start: auto; }

@media (max-width: 640px) {
    /* En teléfono no hay ancho para separarlos de lado: se apilan, y el
       destructivo queda abajo, lejos del pulgar que viene de «Guardar». */
    .tb-pin-acciones { flex-direction: column; align-items: stretch; gap: 14px; }
    .tb-pin-acciones > *:last-child:not(:first-child) { margin-inline-start: 0; }
    .tb-pin-estado { flex-wrap: wrap; }
    .tb-pin-estado__chip { order: -1; }
}

/* ══════════════════════════════════════════════════════════════════════
   DESPLEGABLES EN MÓVIL · ancho, nunca altura
   Al acotar el bloque de escritorio se fue también lo único que en el
   teléfono sí hacía falta: decirle al desplegable que ocupe TODO el ancho
   de su caja. Sin eso el botón se encoge al ancho de su contenido y una
   etiqueta como «Otro…» se parte letra por letra en vertical, estirando el
   campo hacia abajo y encabalgándose con la etiqueta de al lado. Se veía al
   editar una unidad fuera de la lista (litro, saco, bolsa…).

   REGLA DE ORO: acá se toca ANCHO, jamás altura ni display. El desplegable
   no nativo dibuja su panel de opciones dentro de esta misma caja, y
   cualquier altura impuesta lo aplasta.
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 767px) {
    .fi-fo-field .fi-fo-select .fi-select-input:not(select),
    .fi-fo-field .fi-fo-select .fi-select-input-ctn,
    .fi-fo-field .fi-fo-select .fi-select-input-btn {
        width: 100%;
        min-width: 0;
        max-width: 100%;
    }
    /* El valor va en una línea: si no cabe, puntos suspensivos. */
    .fi-fo-field .fi-fo-select .fi-select-input-value-label,
    .fi-fo-field .fi-fo-select .fi-select-input-placeholder {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        min-width: 0;
    }
    /* Las opciones del panel sí pueden ocupar dos líneas. */
    .fi-fo-field .fi-fo-select [role="option"] { white-space: normal; }
}

/* ══════════════════════════════════════════════════════════════════════
   MENÚ LATERAL ABIERTO EN MÓVIL · la página de atrás no se mueve
   Con el menú desplegado, arrastrar el dedo desplazaba el contenido de
   abajo: se perdía el sitio donde uno estaba y el menú parecía flotar
   sobre algo que se movía solo. La marca la pone el propio menú (ver
   resources/views/filament/sidebar-close.blade.php) y sólo en móvil.
   ══════════════════════════════════════════════════════════════════════ */
html.tb-menu-abierto,
html.tb-menu-abierto body {
    overflow: hidden;
    /* Corta el "rebote" que en iOS pasa el gesto a la página de atrás. */
    overscroll-behavior: none;
}
/* El fondo oscuro no es contenido: ahí el dedo no debe desplazar nada. */
html.tb-menu-abierto .fi-sidebar-close-overlay { touch-action: none; }
/* Dentro del menú sí se desplaza, pero el gesto se queda ahí: al llegar al
   final de la lista no continúa arrastrando lo de atrás. */
html.tb-menu-abierto .fi-sidebar { overscroll-behavior: contain; }

/* ══════════════════════════════════════════════════════════════════════
   CASILLA DE SELECCIÓN DE LAS TABLAS
   Marcada, Filament le deja su sombra proyectada (0 1px 3px negro al 10%).
   Sobre el verde y en fondo oscuro esa sombra se lee como una franja más
   oscura pegada al borde de abajo, como si el icono estuviera mal recortado.
   El relleno verde ya la distingue de sobra; la sombra sólo ensucia.
   ══════════════════════════════════════════════════════════════════════ */
.fi-ta-record-checkbox,
.fi-ta-record-checkbox:checked { box-shadow: none !important; }

/* ══════════════════════════════════════════════════════════════════════
   ETIQUETA JUNTO AL NOMBRE (tipo de documento)
   Distintivo pequeño que acompaña al título en la misma línea, en vez de
   ocupar una columna propia. Discreto a propósito: el que manda es el
   nombre del documento, la etiqueta sólo lo clasifica.
   ══════════════════════════════════════════════════════════════════════ */
.tb-etiqueta {
    display: inline-block;
    margin-inline-start: .4rem;
    padding: .05rem .4rem;
    border-radius: 999px;
    font-size: .68rem;
    font-weight: 600;
    line-height: 1.5;
    letter-spacing: .01em;
    vertical-align: middle;
    white-space: nowrap;
    color: #1C6146;
    background: #E8F5EF;
}
.dark .tb-etiqueta { color: #83D1B0; background: rgb(112 199 163 / .14); }

/* ══════════════════════════════════════════════════════════════════════════
   INICIO · sistema visual propio
   ══════════════════════════════════════════════════════════════════════════
   Las tarjetas de estadística que trae Filament se ven como las de cualquier
   panel hecho con Filament: mismo recuadro, misma tipografía, mismo peso para
   el número y para su etiqueta. Sirven, pero no dicen nada de la marca ni
   jerarquizan.
   Acá el número manda —tipografía display, grande, apretada—, la etiqueta va
   arriba en versalitas y el contexto abajo en gris. El icono ocupa una esquina
   y no compite. Todo comparte radio, borde y sombra con el resto del panel.  */

.tb-ico { width: 100%; height: 100%; display: block; }

/* ── Rejilla de tarjetas ───────────────────────────────────────────────── */
.tb-panel { display: grid; gap: 12px; grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* La primera ocupa dos columnas: es el dato del día y con siete tarjetas en una
   rejilla de cuatro, además, deja la segunda fila completa en vez de con un
   hueco suelto al final. */
.tb-tarj--ancha { grid-column: span 2; }
@media (max-width: 640px) { .tb-tarj--ancha { grid-column: span 2; } }
@media (max-width: 1279px) { .tb-panel { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* En el teléfono se mantienen DOS por fila. Con una sola, siete tarjetas
   obligaban a desplazar media pantalla por dato, y el panel dejaba de servir
   para lo que existe: ver el estado de un vistazo. */
@media (max-width: 900px)  { .tb-panel { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.tb-tarj {
    position: relative; overflow: hidden;
    background: #fff; border: 1px solid rgb(15 23 42 / .07); border-radius: 16px;
    padding: 16px 16px 14px; text-decoration: none; color: inherit; display: block;
    transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.dark .tb-tarj { background: var(--tb-d-card, #242426); border-color: var(--tb-d-border, rgba(255,255,255,.09)); }

/* Filo de color arriba: identifica el estado sin pintar la tarjeta entera. */
.tb-tarj::before {
    content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
    background: var(--filo, transparent); opacity: .9;
}
.tb-tarj--ir { cursor: pointer; }
.tb-tarj--ir:hover { transform: translateY(-2px); box-shadow: 0 10px 24px -14px rgb(15 23 42 / .45); border-color: rgb(37 117 84 / .35); }

.tb-tarj__cab { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.tb-tarj__et {
    font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
    color: rgb(100 116 139); line-height: 1.35;
}
.dark .tb-tarj__et { color: rgb(148 163 184); }

.tb-tarj__ico {
    flex: none; width: 34px; height: 34px; border-radius: 10px; padding: 8px;
    background: var(--tinte, rgb(148 163 184 / .12)); color: var(--filo, #64748b);
}

.tb-tarj__num {
    font-family: var(--tb-display, inherit); font-weight: 600;
    font-size: 34px; line-height: 1.05; letter-spacing: -.035em;
    color: #0f172a; margin-top: 10px;
}
.tb-tarj--ancha { padding: 18px 20px 16px; }
.tb-tarj--ancha .tb-tarj__num { font-size: 44px; margin-top: 14px; }
.tb-tarj--ancha .tb-tarj__ico { width: 38px; height: 38px; padding: 9px; }
.dark .tb-tarj__num { color: #f4f4f5; }
.tb-tarj__num small { font-size: 15px; font-weight: 600; letter-spacing: -.01em; color: rgb(100 116 139); margin-left: 3px; }

.tb-tarj__pie { margin-top: 4px; font-size: 12.2px; line-height: 1.45; color: rgb(100 116 139); }
.dark .tb-tarj__pie { color: rgb(148 163 184); }
.tb-tarj__pie b { color: var(--filo, inherit); font-weight: 700; }

/* Tonos. El filo y el tinte del icono salen del mismo color. */
.tb-t--verde  { --filo: #257554; --tinte: rgb(37 117 84 / .12); }
.tb-t--ambar  { --filo: #B45309; --tinte: rgb(180 83 9 / .12); }
.tb-t--rojo   { --filo: #B91C1C; --tinte: rgb(185 28 28 / .11); }
.tb-t--gris   { --filo: #94A3B8; --tinte: rgb(148 163 184 / .14); }
.dark .tb-t--verde { --filo: #70C7A3; --tinte: rgb(112 199 163 / .15); }
.dark .tb-t--ambar { --filo: #F5B461; --tinte: rgb(245 180 97 / .15); }
.dark .tb-t--rojo  { --filo: #F0857D; --tinte: rgb(240 133 125 / .15); }

/* ── Agenda del día ────────────────────────────────────────────────────── */
.tb-agenda__lista { display: flex; flex-direction: column; }
.tb-cita {
    display: flex; align-items: center; gap: 14px; padding: 12px 2px;
    border-top: 1px solid rgb(15 23 42 / .06); text-decoration: none; color: inherit;
}
.tb-cita:first-child { border-top: 0; padding-top: 4px; }
.dark .tb-cita { border-top-color: rgb(255 255 255 / .07); }

/* La hora en una pastilla: es el dato por el que se busca en la lista. */
.tb-cita__hora {
    flex: none; width: 62px; text-align: center; border-radius: 12px; padding: 7px 0;
    background: rgb(37 117 84 / .09);
}
.dark .tb-cita__hora { background: rgb(112 199 163 / .13); }
.tb-cita__h { font-family: var(--tb-display, inherit); font-size: 16px; font-weight: 600; letter-spacing: -.02em; color: #1C6146; line-height: 1.1; }
.dark .tb-cita__h { color: #83D1B0; }
.tb-cita__d { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #257554; opacity: .75; margin-top: 1px; }
.dark .tb-cita__d { color: #70C7A3; }

/* Hoy se distingue del resto sin gritar. */
.tb-cita--hoy .tb-cita__hora { background: #257554; }
.tb-cita--hoy .tb-cita__h, .tb-cita--hoy .tb-cita__d { color: #fff; opacity: 1; }

.tb-cita__cuerpo { flex: 1; min-width: 0; }
.tb-cita__tit { font-size: 14.5px; font-weight: 600; color: #0f172a; line-height: 1.3; overflow-wrap: anywhere; }
.dark .tb-cita__tit { color: #f4f4f5; }
.tb-cita__sub { font-size: 12.4px; color: rgb(100 116 139); margin-top: 2px; line-height: 1.4; overflow-wrap: anywhere; }
.dark .tb-cita__sub { color: rgb(148 163 184); }

.tb-cita__estado {
    flex: none; font-size: 11px; font-weight: 700; letter-spacing: .03em;
    padding: 4px 9px; border-radius: 999px; white-space: nowrap;
}
.tb-e--ok { background: rgb(37 117 84 / .12); color: #1C6146; }
.tb-e--pend { background: rgb(180 83 9 / .12); color: #92400E; }
.dark .tb-e--ok { background: rgb(112 199 163 / .15); color: #83D1B0; }
.dark .tb-e--pend { background: rgb(245 180 97 / .15); color: #F5B461; }

.tb-vacio { padding: 26px 16px; text-align: center; color: rgb(100 116 139); font-size: 13.5px; }
.tb-vacio__ico { width: 34px; height: 34px; margin: 0 auto 10px; color: rgb(148 163 184); }

@media (max-width: 640px) {
    .tb-cita { gap: 11px; }
    .tb-cita__hora { width: 54px; }
    .tb-cita__estado { display: none; }

    /* Tarjetas más apretadas: con dos por fila, el aire de escritorio sobra. */
    .tb-panel { gap: 10px; }
    .tb-tarj { padding: 12px 12px 11px; border-radius: 14px; }
    .tb-tarj__et { font-size: 9.5px; letter-spacing: .06em; }
    .tb-tarj__ico { width: 28px; height: 28px; padding: 6px; border-radius: 8px; }
    .tb-tarj__num { font-size: 27px; margin-top: 6px; }
    .tb-tarj__pie { font-size: 11.4px; margin-top: 2px; }
    .tb-tarj--ancha { padding: 14px 14px 12px; }
    .tb-tarj--ancha .tb-tarj__num { font-size: 34px; margin-top: 8px; }
    .tb-tarj--ancha .tb-tarj__ico { width: 32px; height: 32px; padding: 7px; }

    /* Los accesos rápidos no parten la palabra en dos líneas. */
    .tb-quickgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
    .tb-quick { padding: 11px 12px; font-size: 12.5px; }
    .tb-quick svg { width: 16px; height: 16px; }
    .tb-hero__greet { font-size: clamp(24px, 7vw, 30px); }
    .tb-hero__resumen { font-size: 12.5px; gap: 6px 14px; }
}

/* ── Bienvenida ───────────────────────────────────────────────────────────
   Antes era un saludo grande y una fila de botones iguales. Ahora la barra
   trae además la FECHA y el dato del día —cuántas citas y a qué hora la
   próxima—, que es lo que se busca al abrir. Los accesos pasan a ser piezas
   con icono propio y jerarquía: el primero es la acción principal del rubro. */
.tb-hero__fecha {
    font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
    color: rgba(255,255,255,.42); margin-bottom: 10px;
}
.tb-hero__resumen {
    display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 14px;
    font-size: 13.5px; color: rgba(255,255,255,.72);
}
.tb-hero__dato { display: inline-flex; align-items: center; gap: 8px; }
.tb-hero__dato svg { width: 16px; height: 16px; color: #70C7A3; flex: none; }
.tb-hero__dato b { color: #fff; font-weight: 600; }

.tb-quick {
    gap: 10px; padding: 12px 14px; justify-content: flex-start;
    font-size: 13.5px; font-weight: 600;
}
.tb-quick svg { width: 18px; height: 18px; flex: none; color: #70C7A3; }
/* La primera es la acción principal del rubro: se rellena para que se vea. */
.tb-quick--principal { background: #257554; border-color: #257554; color: #fff; }
.tb-quick--principal svg { color: #fff; }
.tb-quick--principal:hover { background: #2C8A63; border-color: #2C8A63; color: #fff; }

@media (max-width: 720px) {
    .tb-quickgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .tb-hero { padding: 22px 20px; }
}
