/* =====================================================================
   SKINS Y MODO (claro/oscuro): PARAMETRIZACIÓN
   =====================================================================
   Dos selectores independientes en <html> (puestos por app.js en cuanto se
   conoce la sesión, ver public/components/app/app.js):
     [data-skin="choco" | "green" | "sky"]   -- familia visual (forma/paleta/densidad)
     [data-mode="light" | "dark"]    -- claro u oscuro, cruzado con cualquier skin
   Esto da 4 combinaciones reales. Se define primero el conjunto de variables
   "neutras" (compartidas por ambos skins: espaciado, tipografía, alturas de
   control) y luego cada bloque [data-skin]/[data-mode] pisa solo lo que
   cambia (colores, sombras, radios) -- así un futuro skin nuevo solo necesita
   definir SUS variables de color/forma, no repetir toda la hoja.

   Límite duro del proyecto: --radius/--radius-lg NUNCA pasan de 4px en
   NINGÚN skin (Choco, Green, Sky, ni ninguno futuro) -- salvo imágenes o casos
   muy puntuales señalados explícitamente. Ver regla de border-radius en la
   memoria del proyecto. */

:root {
    color-scheme: light;

    /* ---- Variables de apariencia SIN valor por defecto propio ----
       Cada combinación skin+modo las define; existen aquí solo para que un
       componente que se cargue antes de que se resuelva el atributo (muy
       improbable, pero por si acaso) no rompa por variable inexistente. */
    --bg: #e9eff8;
    --surface: #ffffff;
    --surface-soft: #f4f7fb;
    --surface-elevated: #ffffff;
    --border: #cfd8e6;
    /* Borde más marcado para botones de fondo claro (secundarios), para que
       se distinga bien su forma sobre paneles igual de claros. */
    --border-strong: #94a3b8;
    --text: #111827;
    --text-soft: #5f6b7c;
    --primary: #1e5bd8;
    --primary-dark: #0b3a9e;
    --danger: #c0392b;
    --danger-dark: #962d21;
    --success: #34c98e;
    --success-dark: #1fa872;
    --success-soft: #eefaf2;
    --success-soft-strong: #dcefe4;
    --danger-soft: #e11d48;
    --warning: #b45309;
    --warning-soft: rgba(251, 191, 36, 0.16);
    --warning-border: rgba(217, 119, 6, 0.26);
    --schedule-request: #0d9488;
    --schedule-request-dark: #0f766e;
    --fichaje-request: #7c3aed;
    --fichaje-request-dark: #6d28d9;
    --surface-hover: #eef3f8;
    --shadow: 0 20px 45px rgba(15, 23, 42, 0.12);
    --shadow-soft: 0 10px 26px rgba(15, 23, 42, 0.07);
    --radius: 3px;
    --radius-lg: 3px;
    --topbar-height: 58px;

    /* ---- Fondos/gradientes que antes estaban hardcodeados en body/topbar/inputs ---- */
    --body-bg-gradient: radial-gradient(circle at top, rgba(29, 78, 216, 0.08) 0%, rgba(29, 78, 216, 0) 32%),
        linear-gradient(180deg, #f3f7fd 0%, #e9eff8 55%, #e2eaf6 100%);
    --topbar-gradient: linear-gradient(90deg, #0b3a9e 0%, #1e5bd8 100%);
    --input-bg: #fbfcfe;
    --input-bg-disabled: #f2f5f9;
    --input-bg-focus: #ffffff;
    --sidebar-surface: rgba(255, 255, 255, 0.94);
    --sidebar-link-bg: #f8fafc;
    --sidebar-link-hover-bg: #f3f7fc;
    --sidebar-link-border: #e2e8f0;
    --modal-header-bg: linear-gradient(180deg, #fbfcfe 0%, #f7f9fc 100%);
    --modal-footer-bg: #f8fafc;
    --modal-border: rgba(207, 216, 230, 0.95);
    --modal-backdrop: rgba(15, 23, 42, 0.58);

    /* ---- Escala de espaciado "compacto moderado" ----
       Un único juego de valores para paddings/gaps de toda la app: así una
       tarjeta de Almacén y una de Laboral usan literalmente los mismos
       números, en vez de que cada módulo invente los suyos parecidos pero
       no iguales (que es como se llegó a la mezcla de valores sueltos que
       había antes: 8px aquí, 10px allá, 12px más allá, todos "casi" el mismo
       aire pero sin ser el mismo). Progresión pensada para dar pasos claros
       al ojo (no valores tan pegados que no se note la diferencia):
       2 / 4 / 8 / 12 / 16 / 24px. Usar SIEMPRE una de estas seis, nunca un
       px suelto nuevo, salvo casos muy puntuales (p. ej. 1px de borde). */
    --space-1: 2px;
    --space-2: 4px;
    --space-3: 8px;
    --space-4: 12px;
    --space-5: 16px;
    --space-6: 24px;

    /* ---- Escala tipográfica compacta ----
       Base más pequeña que el 16px "de folleto" por defecto del navegador:
       con más densidad de información en pantalla (tablas, KPIs, formularios
       largos) un texto de cuerpo a 13-14px sigue siendo cómodo de leer y dejar
       más aire para los datos importa más que el tamaño de letra. "xs" es para
       etiquetas/metadatos (uppercase, poco peso visual); "lg" para títulos de
       tarjeta/sección, no para h1-h4 (que ya tienen su propia escala arriba). */
    --font-size-xs: 0.72rem;
    --font-size-sm: 0.82rem;
    --font-size-base: 0.88rem;
    --font-size-md: 0.95rem;
    --font-size-lg: 1.05rem;

    /* ---- Alturas de control estándar ----
       "sm" para filas de tabla, chips y controles secundarios muy repetidos;
       "md" para inputs/selects/botones normales. Nunca bajar de 32px en algo
       que se pulsa (checkbox, botón, input) -- por debajo de eso el área de
       toque en móvil se vuelve incómoda aunque en PC "se vea bien". Una fila
       de tabla NO interactiva (solo lectura) sí puede ser más baja que esto. */
    --control-height-sm: 32px;
    --control-height-md: 38px;

    /* ---- Pestañas y subpestañas ----
       Mismo alto y mismo padding horizontal para CUALQUIER fila de tabs de la
       app (pestañas principales, subpestañas, chips de filtro tipo pestaña):
       es el detalle que más se nota cuando dos módulos "no se sienten iguales"
       aunque compartan colores. */
    --tab-height: 38px;
    --tab-padding-x: var(--space-4);
}


* {
    box-sizing: border-box;
}

/* TODA la app mide sus fuentes en rem (ningún módulo usa em ni px sueltos para texto), y "1rem"
   se calcula siempre sobre el font-size de <html> -- que nunca se había fijado, así que seguía en
   los 16px por defecto del navegador. Los tokens --font-size-* nuevos (definidos más abajo) son
   compactos, pero solo se notaban en los pocos sitios donde se aplicaron uno a uno: cualquier
   "1rem"/"1.1rem" suelto en cualquiera de los 11 módulos seguía partiendo de 16px, por eso se veía
   "todo desigual" en vez de compacto de verdad. Bajar la base aquí compacta TODA la app de golpe,
   de forma coherente, sin tener que tocar cada módulo uno a uno para conseguirlo. */
html {
    font-size: 87.5%;
    /* Salvaguarda: al ser una SPA sin recarga de página, si CUALQUIER vista
       desborda el ancho del documento (un grid/flex mal calculado, un texto
       largo sin wrap...) ese overflow horizontal persistía visualmente al
       cambiar a otra vista sin culpa propia -- bug real reportado ("todas
       las pantallas se ven igual de mal", cuando la causa real estaba solo
       en el Dashboard de admin). overflow-x:hidden aquí no arregla la causa
       (eso se corrige en el origen, ver .labor-dashboard-grid--sesame más
       abajo) pero evita que un desbordamiento puntual contamine el resto
       de la navegación sin recargar. */
    overflow-x: hidden;
}

body {
    margin: 0;
    min-height: 100vh;
    overflow-x: hidden;
    /* clip recorta igual que hidden pero NO convierte al body en contenedor de
       scroll -- con hidden, position:sticky del menú lateral no funcionaba
       porque se anclaba al body (que nunca hace scroll) y no a la ventana. */
    overflow-x: clip;
    font-family: Inter, Arial, sans-serif;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    background: var(--body-bg-gradient);
    color: var(--text);
}

body[data-authenticated='true'] {
    padding-top: var(--topbar-height);
}

button,
input {
    font: inherit;
}

h1, h2, h3, h4, h5, h6 {
    margin: 0;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text);
}

h1 { font-size: 1.5rem; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1.08rem; }
h4 { font-size: 0.96rem; }

[hidden] {
    display: none !important;
}

.app-shell {
    width: min(98vw, 1900px);
    margin: 0 auto;
    padding: 0 0 32px;
}

body[data-authenticated='true'] .app-shell {
    padding-top: 0;
}

.app-topbar {
    position: fixed;
    inset: 0 0 auto;
    /* Por encima de cualquier control de Leaflet (zoom, pantalla completa...), que usa
       z-index 1000 por defecto — con el mismo valor, el menú y los iconos del mapa competían
       y a veces ganaba el mapa, tapando el menú principal. */
    z-index: 2000;
    background: var(--topbar-gradient);
    border-bottom: 1px solid rgba(255, 255, 255, 0.14);
    box-shadow: 0 16px 32px rgba(15, 23, 42, 0.16);
    backdrop-filter: blur(14px);
}

.app-topbar__inner {
    width: min(98vw, 1900px);
    min-height: var(--topbar-height);
    margin: 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 24px;
}

.app-topbar__session {
    flex: 1 1 auto;
    min-width: 0;
}

.app-topbar__label {
    display: none;
}

.app-topbar__identity {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: nowrap;
    min-width: 0;
}

.app-topbar__menu-toggle.button--secondary,
/* Aviso "login as": bien visible en la topbar mientras se está suplantando
   a otra cuenta, con el mismo alto que el resto de la barra (no añade una
   fila nueva ni desplaza el contenido). */
.app-topbar__impersonation {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-right: 10px;
    padding: 6px 6px 6px 12px;
    border-radius: var(--radius);
    background: rgba(251, 191, 36, 0.16);
    border: 1px solid rgba(217, 119, 6, 0.4);
    color: #fef3c7;
}

.app-topbar__impersonation-icon {
    display: inline-flex;
    width: 16px;
    height: 16px;
    color: #fbbf24;
    flex: 0 0 auto;
}

.app-topbar__impersonation-icon svg {
    width: 100%;
    height: 100%;
    display: block;
}

.app-topbar__impersonation-text {
    font-size: 0.82rem;
    color: #fef3c7;
    white-space: nowrap;
}

.app-topbar__impersonation-text strong {
    color: #fff;
}

.app-topbar__impersonation-exit.button--secondary {
    min-height: 28px;
    padding: 0 10px;
    font-size: 0.76rem;
    background: rgba(255, 255, 255, 0.1);
    border-color: rgba(251, 191, 36, 0.5);
    color: #fef3c7;
    box-shadow: none;
    min-width: 0;
}

.app-topbar__impersonation-exit.button--secondary:hover {
    background: rgba(255, 255, 255, 0.18);
}

.app-topbar__work-indicator,
.app-topbar__break-indicator {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    min-width: 38px;
    height: 38px;
    margin-right: 10px;
    border-radius: 3px;
    font-size: 1.05rem;
    line-height: 1;
}

.app-topbar__work-indicator {
    background: var(--success, #1f9d55);
    color: #ffffff;
}

.app-topbar__break-indicator {
    background: #f5c518;
    color: #1a1a1a;
}

/* Redundante con el indicador de trabajando/descanso de la topbar (pedido
   explícito): se quita en todos los subskins del reloj de fichaje. */
.tc-hud__state {
    display: none !important;
}

.app-topbar__logout.button--secondary {
    width: 38px;
    min-width: 38px;
    padding: 0;
    border-color: rgba(255, 255, 255, 0.16);
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    box-shadow: none;
    flex: 0 0 38px;
}

.app-topbar__menu-toggle.button--secondary:hover,
.app-topbar__logout.button--secondary:hover {
    background: rgba(255, 255, 255, 0.14);
}

body[data-sidebar-open='true'] .app-topbar__menu-toggle.button--secondary {
    /* Antes azul fijo: este botón vive SIEMPRE sobre el degradado de marca del
       topbar (--topbar-gradient, azul en Sky pero naranja en Choco) -- un
       resalte azul ahí desentonaba en cualquier skin no-azul. Blanco
       translúcido, coherente con el :hover de la línea de arriba, funciona
       igual de bien sobre cualquier color de fondo. */
    border-color: rgba(255, 255, 255, 0.4);
    background: rgba(255, 255, 255, 0.22);
}

.app-topbar__menu-icon,
.app-topbar__logout-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}

.app-topbar__menu-icon svg,
.app-topbar__logout-icon svg {
    width: 20px;
    height: 20px;
    display: block;
}

/* Contenedor de la foto/nombre + mini menú de skins (un clic; doble clic abre
   el perfil). El menú cuelga bajo la barra, alineado a la derecha del botón. */
.app-topbar__profile-wrap {
    position: relative;
    display: inline-flex;
    min-width: 0;
    max-width: 100%;
}

.app-profile-menu {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    z-index: 2100;
    min-width: 190px;
    padding: 6px;
    border: 1px solid var(--border-strong);
    border-radius: 3px;
    background: var(--surface-elevated);
    color: var(--text);
    box-shadow: var(--shadow);
}

.app-profile-menu[hidden] {
    display: none;
}

.app-profile-menu__label {
    margin: 8px 8px 4px;
    color: var(--text-soft);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

.app-profile-menu__item {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 8px;
    border: 0;
    border-radius: 3px;
    background: transparent;
    color: var(--text);
    font-size: 0.82rem;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
}

.app-profile-menu__item:hover,
.app-profile-menu__item:focus-visible {
    background: var(--surface-hover);
    outline: none;
}

/* Interruptor de modo oscuro y selector de diseño de Fichajes dentro del menú:
   misma estética de ítem del menú. El título del selector de diseño se oculta
   solo cuando el selector está oculto (fuera de Fichajes). */
.app-profile-menu .app-sidebar__mode-toggle {
    justify-content: flex-start;
}

.app-profile-menu .app-sidebar__mode-toggle .app-sidebar__mode-switch {
    margin-left: auto;
}

.app-profile-menu .app-sidebar__skin-switch {
    margin: 4px 2px 2px;
}

.app-profile-menu__label--layout:has(+ [data-timeclock-layout-switch][hidden]) {
    display: none;
}

/* "Mi perfil": primer ítem, con icono y una línea separadora debajo. */
.app-profile-menu__profile {
    margin-bottom: 4px;
    padding-bottom: 9px;
    border-bottom: 1px solid var(--border);
    border-radius: 3px 3px 0 0;
    font-weight: 700;
}

.app-profile-menu__icon {
    flex: none;
    width: 16px;
    height: 16px;
    color: var(--primary);
}

.app-profile-menu__dot {
    flex: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--dot, var(--primary));
    box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.35), 0 0 0 1px rgba(0, 0, 0, 0.18);
}

.app-profile-menu__skin[aria-pressed='true'] {
    background: color-mix(in srgb, var(--primary) 13%, var(--surface-elevated));
    box-shadow: inset 3px 0 0 var(--primary);
}

.app-topbar__profile {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
    text-align: left;
    min-width: 0;
    max-width: 100%;
}

.app-topbar__profile:focus-visible {
    outline: 2px solid rgba(191, 219, 254, 0.88);
    outline-offset: 3px;
    border-radius: var(--radius);
}

.app-topbar__avatar {
    width: 38px;
    height: 38px;
    flex: 0 0 38px;
    display: grid;
    place-items: center;
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: var(--radius-lg);
    background: rgba(255, 255, 255, 0.08);
}

.app-topbar__avatar-image {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
}

.app-topbar__avatar-fallback {
    color: #fff;
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1;
}

.app-topbar__profile-copy {
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    overflow: hidden;
}

.app-topbar__profile:hover .app-topbar__name,
.app-topbar__profile:focus-visible .app-topbar__name {
    text-decoration: underline;
}

.app-topbar__name {
    color: #fff;
    font-size: 0.92rem;
    letter-spacing: -0.02em;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-topbar__role {
    color: rgba(226, 232, 240, 0.82);
    font-size: 0.78rem;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-shell__layout {
    position: relative;
    display: grid;
    grid-template-columns: 0 minmax(0, 1fr);
    gap: 0;
    align-items: start;
    transition: grid-template-columns 0.22s ease, gap 0.22s ease;
}

body[data-authenticated='true'][data-sidebar-open='true'] .app-shell__layout {
    grid-template-columns: 220px minmax(0, 1fr);
    gap: 12px;
}

.app-sidebar {
    grid-column: 1;
    position: static;
    align-self: start;
    margin-top: 10px;
    max-height: none;
    min-width: 0;
    overflow: visible;
    opacity: 0;
    pointer-events: none;
    transform: translateX(-18px);
    transition: opacity 0.2s ease, transform 0.2s ease;
}

body[data-authenticated='true'][data-sidebar-open='true'] .app-sidebar {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(0);
}

/* Escritorio: el menú lateral se queda fijo bajo la barra superior al hacer
   scroll vertical (antes era estático y se iba hacia arriba con la página).
   Si el menú es más alto que la ventana, hace scroll por dentro. En móvil
   (<=720px) ya es un panel fijo propio, así que no se toca. El padding con
   margen negativo deja sitio a la sombra de los paneles, que si no el
   overflow la recortaría. */
@media (min-width: 721px) {
    .app-sidebar {
        position: sticky;
        top: calc(var(--topbar-height) + 10px);
        max-height: calc(100dvh - var(--topbar-height) - 20px);
        margin-left: -14px;
        margin-right: -14px;
        padding: 0 14px 18px;
        overflow-x: hidden;
        overflow-y: auto;
        scrollbar-width: thin;
        overscroll-behavior: contain;
    }
}

/* Pie de página de una línea ("Desarrollado por Goatsoft · año"): barra fina
   FIJA abajo del todo, siempre visible (antes iba al final del documento y
   quedaba fuera de pantalla, debajo del menú lateral). Fondo propio con borde
   superior y texto con contraste >= 6:1. Solo con sesión iniciada. Reserva su
   altura con --footer-height (padding del body y barra inferior de Fichajes). */
:root {
    --footer-height: 24px;
}

body[data-authenticated='true'] {
    padding-bottom: var(--footer-height);
}

.app-footer {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 900;
    height: var(--footer-height);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    padding: 0 16px;
    border-top: 1px solid var(--border-strong);
    background: var(--surface-elevated);
    color: var(--text-soft);
    font-size: 0.7rem;
    line-height: 1;
    letter-spacing: 0.05em;
    box-shadow: 0 -4px 14px rgba(0, 0, 0, 0.08);
}

.app-footer strong {
    font-weight: 800;
    color: var(--text);
}

.app-footer__link {
    color: var(--text);
    text-decoration: none;
}

.app-footer__link:hover,
.app-footer__link:focus-visible {
    color: var(--primary);
    text-decoration: underline;
    text-underline-offset: 2px;
}

body:not([data-authenticated='true']) .app-footer {
    display: none;
}

.app-sidebar__panel {
    position: relative;
    top: 0;
    max-height: 100%;
    width: 220px;
    /* Padding compacto (ahorro de altura) y su valor en variables, que usa el
       botón Usuarios flotante del panel de Administración. */
    --sb-top: 8px;
    --sb-right: 8px;
    padding: var(--sb-top) var(--sb-right);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--sidebar-surface);
    box-shadow: var(--shadow-soft);
    backdrop-filter: blur(12px);
    overflow-y: auto;
}

.app-sidebar__panel + .app-sidebar__panel {
    margin-top: 6px;
}

/* Toggle claro/oscuro al fondo del sidebar (ver app.js: data-app-mode-toggle).
   Reusa la misma estructura visual que un .app-sidebar__link normal, con un
   interruptor tipo switch a la derecha en vez de una flecha/badge. */
.app-sidebar__mode-toggle {
    justify-content: space-between;
}

.app-sidebar__mode-switch {
    flex: none;
    width: 34px;
    height: 20px;
    border-radius: 999px;
    background: var(--border-strong);
    padding: 2px;
    display: flex;
    align-items: center;
    transition: background 0.2s ease;
}

.app-sidebar__mode-switch-thumb {
    width: 16px;
    height: 16px;
    border-radius: 999px;
    background: var(--surface);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    transform: translateX(0);
    transition: transform 0.2s ease;
}

.app-sidebar__mode-toggle[aria-pressed='true'] .app-sidebar__mode-switch {
    background: var(--primary);
}

.app-sidebar__mode-toggle[aria-pressed='true'] .app-sidebar__mode-switch-thumb {
    transform: translateX(14px);
}

/* Selector de skin (Choco/Green/Sky) al fondo del sidebar, junto al toggle de
   modo: minimalista, segmented control de 2 opciones -- no hace falta ir a
   Perfil solo para cambiar de skin. */
.app-sidebar__skin-switch {
    display: flex;
    gap: 4px;
    margin-top: 6px;
    padding: 3px;
    border-radius: var(--radius);
    background: var(--surface-soft);
}

.app-sidebar__skin-option {
    flex: 1 1 0;
    padding: 6px 0;
    border: 0;
    border-radius: var(--radius);
    background: transparent;
    color: var(--text-soft);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}

.app-sidebar__skin-option:hover {
    color: var(--text);
}

.app-sidebar__skin-option[aria-pressed='true'] {
    background: var(--surface);
    color: var(--primary-dark);
    box-shadow: var(--shadow-soft);
}

/* El selector 1-5 (timeclock-layout-switch) reutiliza el estilo del switch
   de skin del sidebar, pero sus propias reglas en skins/subskins/2-*.css
   fijan display:inline-flex + botones de ancho fijo + margin-left:auto
   (pensado para flotar a la derecha dentro del header de fichar, no para
   ocupar el ancho del sidebar) -- se sobreescribe aquí con más
   especificidad para que los 5 botones se repartan el ancho disponible,
   igual que el switch de skin (Choco/Green/Sky) justo encima. */
.app-sidebar__skin-switch.timeclock-layout-switch {
    display: flex;
    margin-left: 0;
    margin-right: 0;
}

.app-sidebar__skin-switch.timeclock-layout-switch .app-sidebar__skin-option.timeclock-layout-switch__option {
    flex: 1 1 0;
    width: auto;
    height: auto;
    padding: 6px 0;
    border: 1px solid var(--border);
    color: var(--text-soft);
}

.app-sidebar__skin-switch.timeclock-layout-switch .app-sidebar__skin-option.timeclock-layout-switch__option[aria-pressed='true'] {
    background: var(--surface);
    border-color: var(--primary);
    color: var(--primary-dark);
    box-shadow: var(--shadow-soft);
}

.app-sidebar__eyebrow {
    /* Títulos "Menú principal"/"Administración" ocultos para ahorrar altura:
       siguen en el DOM para lectores de pantalla. */
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* "Usuarios" es un trozo de botón pegado a la derecha de "Config": mismo alto
   y mismo aspecto, con una línea fina de separación, para que parezca UN
   botón con dos enlaces. Si "Usuarios" no está disponible (sin permiso), el
   enlace de Config recupera sus 4 esquinas redondeadas. */
.app-sidebar__split {
    display: flex;
    min-width: 0;
}

.app-sidebar__split > .app-sidebar__link {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

.app-sidebar__split-side {
    flex: none;
    width: 38px;
    min-height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--sidebar-link-border);
    border-left-color: var(--border-strong);
    border-radius: 0 var(--radius) var(--radius) 0;
    background: var(--sidebar-link-bg);
    color: var(--text);
    cursor: pointer;
    transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
}

.app-sidebar__split-side svg {
    width: 16px;
    height: 16px;
    display: block;
}

.app-sidebar__split-side:hover {
    background: var(--sidebar-link-hover-bg);
    border-color: var(--border-strong);
}

.app-sidebar__split-side:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary) 18%, transparent);
    outline-offset: 2px;
}

.app-sidebar__split-side.is-active {
    /* Igual que .app-sidebar__link.is-active: resalte con el color de marca
       del skin activo. */
    border-color: color-mix(in srgb, var(--primary) 24%, transparent);
    background: color-mix(in srgb, var(--primary) 8%, transparent);
    color: var(--primary-dark);
    box-shadow: var(--shadow-soft);
}

/* Varios botones laterales (Historial y Usuarios): solo el último redondea el borde derecho; el enlace recupera sus 4 esquinas si no hay ninguno visible */
.app-sidebar__split-side { border-radius: 0; }
.app-sidebar__split-side:not(:has(~ .app-sidebar__split-side:not([hidden]))) { border-radius: 0 var(--radius) var(--radius) 0; }
.app-sidebar__split-side + .app-sidebar__split-side { border-left-color: var(--border-strong); }
.app-sidebar__split:not(:has(> .app-sidebar__split-side:not([hidden]))) > .app-sidebar__link {
    border-radius: var(--radius);
}

.app-sidebar__nav {
    display: grid;
    gap: 4px;
}

.app-sidebar__link {
    position: relative;
    width: 100%;
    min-height: 34px;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 10px;
    border: 1px solid var(--sidebar-link-border);
    border-radius: var(--radius);
    background: var(--sidebar-link-bg);
    color: var(--text);
    cursor: pointer;
    text-align: left;
    font-weight: 700;
    transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
}

.app-sidebar__alert {
    top: -6px;
    right: 6px;
    min-width: 16px;
    width: auto;
    height: 16px;
    padding: 0 4px;
    font-size: 0.6rem;
    border-width: 1px;
}

.app-sidebar__link:hover {
    background: var(--sidebar-link-hover-bg);
    border-color: var(--border-strong);
}

.app-sidebar__link:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary) 18%, transparent);
    outline-offset: 2px;
}

.app-sidebar__link.is-active {
    /* Mismo motivo que .app-sidebar__split-side.is-active más arriba:
       el enlace de menú activo debe resaltar con el color de marca del skin
       activo, no con azul fijo -- si no, en Choco el texto sale naranja pero
       el fondo/borde se quedan azules (justo el efecto "se ve azul" reportado). */
    border-color: color-mix(in srgb, var(--primary) 24%, transparent);
    background: color-mix(in srgb, var(--primary) 8%, transparent);
    color: var(--primary-dark);
    box-shadow: var(--shadow-soft);
}

.app-sidebar__link-icon {
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 18px;
}

.app-sidebar__link-icon svg {
    width: 18px;
    height: 18px;
    display: block;
}

.app-sidebar__link-label {
    min-width: 0;
}

.app-shell__overlay {
    display: none;
}

.app-eyebrow {
    margin: 0 0 6px;
    font-size: 0.76rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--primary);
    font-weight: 700;
}

/* ============================================================
 * Cabecera compacta de módulo (Laboral, Fichajes, Logística...):
 * .labor-hero--compact y .timeclock-hero--compact. Antes esta lógica vivía
 * repetida y descoordinada en 3 sitios (el CSS de cada módulo por skin, MÁS
 * 13 fragmentos sueltos y a veces contradictorios en el antiguo theme.css,
 * exclusivos del skin Blue ya eliminado) -- en pantallas pequeñas ese skin
 * llegaba a tener 3 comportamientos distintos según el breakpoint exacto
 * (fondo de color, luego transparente con texto azul, luego otra variante),
 * mientras Choco/Green solo tenían el primero. Consolidado aquí en UN solo
 * sitio, para los 3 skins actuales, mismo
 * comportamiento en cualquier tamaño de pantalla -- solo el color cambia
 * por skin (var(--primary)/var(--primary-dark), definidas en cada archivo
 * skins/<skin>/labor.css y timeclock.css). Si hace falta tocar esta
 * cabecera en el futuro, es este bloque, no algo disperso en theme.css. */
.labor-hero--compact,
.timeclock-hero--compact {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-5);
    /* Antes sticky con z-index:50: en escritorio el banner (ÁREA LABORAL,
       LOGÍSTICA, etc.) se quedaba pegado justo debajo del topbar al hacer
       scroll, tapando el menú de pestañas de justo debajo (Dashboard/
       Trabajadores/Calendario) -- bug real reportado. Estático en todos los
       tamaños de pantalla, igual que ya se corrigió en móvil. */
    position: static;
    /* --hero-gradient (definido por skin y modo en theme.css) en vez de
       --primary-dark -> --primary: en modo oscuro esos dos son tonos CLAROS
       (pensados como texto sobre fondo oscuro), así que la cabecera salía
       demasiado clara y con el texto blanco sin contraste. */
    background: var(--hero-gradient) !important;
    border: 0 !important;
    color: #fff !important;
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.28) !important;
}

/* :not(.timeclock-punch__state-badge) -- ese badge (dentro de la cabecera de
   Fichajes) tiene su propio color semántico (verde/ámbar) que no debe
   pisarse con el blanco fijo del resto de textos de la cabecera. */
.labor-hero--compact .app-eyebrow,
.labor-hero--compact p:not(.timeclock-punch__state-badge),
.labor-hero--compact span,
.labor-hero--compact label,
.timeclock-hero--compact .app-eyebrow,
.timeclock-hero--compact p:not(.timeclock-punch__state-badge),
.timeclock-hero--compact span,
.timeclock-hero--compact label {
    color: #fff !important;
}

.labor-hero--compact .status:empty,
.timeclock-hero--compact .status:empty {
    display: none;
}

@media (max-width: 720px) {
    .labor-hero--compact,
    .timeclock-hero--compact {
        padding: var(--space-2) var(--space-4);
        gap: var(--space-3);
    }

    /* El interruptor de diseño 1-5 (ver .timeclock-layout-switch) vive en la
       MISMA fila que el título y el "i" en escritorio -- pedido explícito de
       que en móvil pase igual, en vez de bajar a su propia línea aparte
       (ocupaba una fila extra de alto). En vez de flex-wrap, se encoge el
       título (min-width:0 + flex-shrink) y los botones del interruptor
       (más pequeños aquí) hasta que todo cabe en una sola fila real. */
    .timeclock-hero--compact {
        flex-wrap: nowrap;
    }

    .timeclock-hero--compact .app-eyebrow {
        min-width: 0;
        flex-shrink: 1;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .timeclock-hero--compact .timeclock-layout-switch {
        flex-shrink: 0;
        gap: 2px;
        padding: 2px;
        margin-right: 4px;
    }

    .timeclock-hero--compact .timeclock-layout-switch__option {
        width: 19px;
        height: 19px;
        font-size: 0.62rem;
    }

    /* NORMA: la pestaña "Fichajes" (reloj + botones) nunca debe necesitar
       scroll vertical en móvil, cueste lo que cueste de tamaño mínimo --
       pedido explícito ("100%, no dejar que se pueda pasar de ahí en
       ningún caso... no tiene ni que esconderse el header"). Los
       clamp()/dvh puestos en cada tarjeta de diseño (ver
       skins/subskins/*.css) escalan el CONTENIDO, pero sin un tope
       ESTRUCTURAL la suma de partes podía seguir desbordando (bug real
       reportado: "el skin 1 cabe pero los otros no, no se ven los
       botones de abajo"). En vez de restar un número fijo de píxeles
       estimados para la cabecera (frágil, varía según cuántas líneas
       ocupe), TODA la cadena -- body, .app-view, .labor-layout,
       .labor-grid--self, .labor-panel--self-main, el body de la tarjeta,
       el panel de fichar -- se convierte en un único flex-column de
       altura EXACTA 100dvh (topbar ya restada vía su padding-top
       existente en body): cada pieza real (header, pestañas, tarjeta)
       ocupa su alto natural con flex-shrink:0, y la tarjeta absorbe el
       resto con flex:1 min-height:0 -- así el reparto es siempre exacto,
       sin adivinar ninguna cifra. overflow:hidden en la raíz es el tope
       que nunca se puede saltar. */
    /* IMPORTANTE: :has([data-timeclock-layout-switch]) es verdad mientras el
       interruptor 1-5 exista en el DOM, es decir, en TODAS las pestañas de
       Fichajes (Fichajes/Historial/Solicitudes/Ausencias), no solo en la
       de Fichar en sí -- por eso TODA la cadena de aquí en adelante usa
       además :has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden]))
       como condición extra: solo es verdad cuando la pestaña "Fichajes"
       está realmente activa. Sin esta segunda condición, el body entero
       (y por tanto el scroll de Historial/Solicitudes/Ausencias) quedaba
       bloqueado con overflow:hidden aunque el contenido fuera más alto
       que la pantalla -- bug real reportado dos veces ("el historial no
       deja hacer scroll, coge el antiscroll de fichajes"). */
    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) {
        /* border-box: el padding del body (barra superior y pie) cuenta DENTRO de los 100dvh. Sin esto el body medía
           100dvh + barra + pie, se salía de la pantalla y la página se podía mover arriba y abajo. */
        height: 100dvh;
        box-sizing: border-box;
        overflow: hidden;
    }

    html:has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) {
        overflow: hidden;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .app-shell {
        height: calc(100dvh - var(--topbar-height) - var(--footer-height, 0px));
        padding: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .app-shell__layout {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .app-view {
        flex: 1 1 auto;
        min-height: 0;
        min-width: 0;
        display: flex;
        flex-direction: column;
        padding-top: 0;
        overflow: hidden;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .labor-layout {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .timeclock-hero--compact {
        flex-shrink: 0;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .labor-grid--self {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .labor-panel--self-main {
        flex: 1 1 auto;
        min-height: 0;
        min-width: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .labor-panel__body {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .labor-tabs {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .labor-tabs__nav {
        flex-shrink: 0;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden]) {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden]) .labor-tab-stack {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden]) .timeclock-card--cockpit {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]):has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) .labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden]) .timeclock-card--cockpit .labor-card-section__body {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    /* El HUD (reloj) y la fila de fichar se reparten lo que sobra del
       cuerpo de la tarjeta; el HUD no crece más de lo necesario
       (flex-shrink permitido, flex-grow no), la zona de fichar absorbe el
       resto del alto disponible y centra su contenido verticalmente. */
    body[data-authenticated='true']:has([data-timeclock-layout-switch]) .labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden]) .timeclock-card--cockpit .tc-hud {
        flex: 0 1 auto;
        min-height: 0;
    }

    body[data-authenticated='true']:has([data-timeclock-layout-switch]) .labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden]) .timeclock-card--cockpit .timeclock-punch {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        justify-content: center;
        overflow: hidden;
    }
}

/* Bolita "i" amarilla en la cabecera de Fichajes: abre el historial de
   mensajes de hoy (ver .timeclock-messages-banner más abajo). margin-left:auto
   la empuja al extremo derecho de la cabecera sin desplazar el resto -- el
   interruptor de diseño 1-5 (.timeclock-layout-switch) también lleva su
   propio margin-left:auto y va antes en el HTML, así que en la práctica es
   el que agrupa ambos controles a la derecha; este de aquí queda como
   fallback si algún día el interruptor volviera a ocultarse. */
.timeclock-messages-info {
    margin-left: auto;
    flex: none;
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: #fbbf24;
    cursor: pointer;
}

.timeclock-messages-info__dot {
    font-size: 0.82rem;
    font-weight: 800;
    font-style: italic;
    color: #78350f;
    line-height: 1;
}

/* Flotante fijo en el centro vertical de la pantalla, pegado al borde
   derecho (pedido explícito, tras quitar la cabecera de Fichajes que lo
   contenía). z-index por encima del contenido pero por debajo de modales. */
.timeclock-messages-info--floating {
    position: fixed;
    top: 50%;
    right: 0;
    transform: translateY(-50%);
    margin-left: 0;
    width: 32px;
    height: 32px;
    border-radius: 3px 0 0 3px;
    z-index: 40;
    box-shadow: -1px 1px 4px rgba(0, 0, 0, 0.18);
}

/* Único sitio para todos los avisos de fichar/pausar (antes dispersos en
   varios <p> por la pantalla) -- pedido explícito: se ve un momento y se
   autoculta a los 5s (ver pushTimeclockMessage en timeclock.js) para no
   estorbar, con el historial completo del día accesible desde el botón "i". */
.timeclock-messages-banner {
    /* Mismo ancho máximo que .timeclock-punch (ver skins/*/timeclock.css):
       así en PC se ve tan estrecho como se verá en móvil, a petición
       explícita, en vez de estirarse a lo ancho de toda la tarjeta. */
    max-width: 280px;
    margin: 0 auto;
    padding: 8px 12px;
    border-radius: var(--radius);
    background: var(--surface-soft);
    border: 1px solid var(--border);
    text-align: center;
}

/* Fondo a juego con el color del mensaje (pedido explícito), tinte suave en
   vez de color plano -- mismo criterio que el resto de avisos de la app. */
.timeclock-messages-banner.status--success {
    background: color-mix(in srgb, var(--success) 14%, var(--surface-soft));
    border-color: color-mix(in srgb, var(--success) 35%, var(--border));
}

.timeclock-messages-banner.status--warning {
    background: color-mix(in srgb, var(--warning) 16%, var(--surface-soft));
    border-color: color-mix(in srgb, var(--warning) 35%, var(--border));
}

.timeclock-messages-banner.status--error {
    background: color-mix(in srgb, var(--danger) 14%, var(--surface-soft));
    border-color: color-mix(in srgb, var(--danger) 35%, var(--border));
}

.timeclock-messages-modal-list .status.status--success {
    background: color-mix(in srgb, var(--success) 12%, transparent);
    border-radius: var(--radius);
    padding: 8px 10px;
}

.timeclock-messages-modal-list .status.status--warning {
    background: color-mix(in srgb, var(--warning) 14%, transparent);
    border-radius: var(--radius);
    padding: 8px 10px;
}

.timeclock-messages-modal-list .status.status--error {
    background: color-mix(in srgb, var(--danger) 12%, transparent);
    border-radius: var(--radius);
    padding: 8px 10px;
}

.timeclock-messages-modal-list .status {
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
}

.timeclock-messages-modal-list .status:last-child {
    border-bottom: none;
}

.app-title {
    margin: 0;
    font-size: clamp(1.9rem, 3vw, 2.9rem);
    letter-spacing: -0.03em;
}

.app-subtitle {
    max-width: 520px;
    margin: 0;
    color: var(--text-soft);
    line-height: 1.5;
}

/* Mientras un módulo carga sus datos iniciales la vista no se ve (evita parpadeos de bloques que se rellenan u ocultan). */
.app-view--loading { opacity: 0; }
.app-view:not(.app-view--loading) { transition: opacity .12s ease-out; }

.app-view {
    grid-column: 2;
    min-height: calc(100vh - 120px);
    min-width: 0;
    padding-top: 8px;
}

.panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    /* Sombra neutra (antes azul fijo rgba(11,58,158,...) -- se notaba como
       tinte azulado en CUALQUIER panel de la app, incluso en skins cuyo color
       de marca no es azul, p. ej. Choco terracota). var(--shadow-soft) ya usa
       un neutro (rgba(15,23,42,...), casi negro) definido por cada skin. */
    box-shadow: var(--shadow-soft);
    overflow: hidden;
}

.panel--compact {
    padding: 24px;
}

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 38px;
    padding: 0 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    cursor: pointer;
    font-size: 0.86rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    box-shadow: var(--shadow-soft);
    transition: transform 0.15s ease, background 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.button:hover {
    background: var(--surface-hover);
    border-color: #b7c5d9;
    box-shadow: 0 12px 26px rgba(15, 23, 42, 0.08);
    transform: translateY(-1px);
}

.button:active {
    transform: translateY(0);
}

/* ---- Iconos SVG (Lucide, en /assets/icons) en vez de emoji: mismo trazo
   en toda la app. El tamaño es "em" a propósito, para que siga el
   font-size del texto de al lado en vez de un tamaño fijo (así un icono
   dentro de un botón pequeño no sale más grande que su propio texto), y
   lleva un pelín de margen para que no quede pegado a la palabra vecina. */
.app-icon {
    width: 1.15em;
    height: 1.15em;
    margin-right: 0.35em;
    vertical-align: -0.2em;
    display: inline-block;
    flex-shrink: 0;
}

.app-icon:last-child {
    margin-right: 0;
}

.app-icon--lg {
    width: 1.6em;
    height: 1.6em;
}

/* El SVG de Lucide es negro (currentColor no aplica a <img>): esto lo
   convierte a blanco para usarlo sobre fondos de color u oscuros. */
.app-icon--white {
    filter: brightness(0) invert(1);
}

.button:disabled {
    opacity: 0.7;
    cursor: wait;
    box-shadow: none;
}

.button:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary) 18%, transparent);
    outline-offset: 2px;
}

.button--secondary {
    border-color: var(--border-strong);
    background: var(--surface-soft);
    color: var(--text);
    box-shadow: var(--shadow-soft);
}

.button--secondary:hover {
    background: var(--surface-hover);
    border-color: var(--border-strong);
}

/* Parametrización global de contraste de iconos: cualquier .app-icon dentro
   de un botón de fondo oscuro/de color se pinta de blanco automáticamente,
   y dentro de uno claro (secundario) se queda en negro. Así no hace falta
   ir módulo a módulo repitiendo esta regla cada vez que se añade un botón
   nuevo — solo hay que usar las clases .button--primary/success/danger o
   marcar el botón con .button--icon-dark si tiene un fondo de color que no
   venga de esas clases (p. ej. un color inline). */
.button--primary .app-icon,
.button--success .app-icon,
.button--danger .app-icon,
.button--icon-dark .app-icon {
    filter: brightness(0) invert(1);
}

.button--secondary .app-icon {
    filter: none;
}

.button--primary {
    border-color: var(--primary);
    background: linear-gradient(135deg, var(--primary), var(--primary-dark));
    /* Antes siempre blanco: en Sky oscuro (--primary claro para que combine bien como TEXTO
       sobre fondo oscuro) blanco-sobre-ese-mismo-color-como-FONDO daba contraste insuficiente
       (~3.4:1, por debajo del mínimo 4.5:1). --button-*-ink la define cada bloque de skin/modo
       según haga falta blanco u oscuro para ESTE uso concreto (texto de botón), sin tocar el
       color de fondo/marca en sí. */
    color: var(--button-primary-ink, #fff);
    /* Sombra del color de marca (antes azul fijo): en skins no-azules (Choco)
       un botón naranja con sombra azul se veía incoherente/"sucio". */
    box-shadow: 0 10px 20px color-mix(in srgb, var(--primary) 24%, transparent);
}

.button--primary:hover {
    background: linear-gradient(135deg, var(--primary-dark), var(--primary-dark));
    border-color: var(--primary-dark);
    color: var(--button-primary-ink, #fff);
    box-shadow: 0 14px 30px color-mix(in srgb, var(--primary) 30%, transparent);
}

.button--success {
    border-color: var(--success);
    background: linear-gradient(135deg, var(--success), var(--success-dark));
    /* --success siempre ha sido un verde claro (incluso antes del sistema de skins): blanco
       encima ya daba solo ~2.1:1 de contraste. Mismo mecanismo que --button-primary-ink. */
    color: var(--button-success-ink, #fff);
    box-shadow: 0 10px 20px rgba(31, 143, 95, 0.24);
}

.button--success:hover {
    background: linear-gradient(135deg, var(--success-dark), var(--success-dark));
    border-color: var(--success-dark);
    color: var(--button-success-ink, #fff);
    box-shadow: 0 14px 30px rgba(31, 143, 95, 0.3);
}

.button--danger {
    border-color: var(--danger);
    background: linear-gradient(135deg, var(--danger), var(--danger-dark));
    color: var(--button-danger-ink, #fff);
    box-shadow: 0 10px 20px rgba(192, 57, 43, 0.24);
}

.button--danger:hover {
    background: linear-gradient(135deg, var(--danger-dark), var(--danger-dark));
    border-color: var(--danger-dark);
    color: var(--button-danger-ink, #fff);
    box-shadow: 0 14px 30px rgba(192, 57, 43, 0.3);
}

.hold-confirm-button,
.hold-confirm-button * {
    -webkit-tap-highlight-color: transparent;
}

.hold-confirm-button * {
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}

.hold-confirm-button {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    border-radius: 3px;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    width: 108px;
    height: 108px;
    padding: 0 8px;
    text-align: center;
    line-height: 1.15;
    white-space: normal;
    border-width: 4px;
    border-style: solid;
    border-color: rgba(255, 255, 255, 0.65);
    box-shadow: 0 12px 24px rgba(15, 23, 42, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.35);
}

.hold-confirm-button {
    /* Color del relleno de progreso (ver ::before más abajo): por defecto
       currentColor (el texto del propio botón) -- así se ve bien en Sky
       oscuro (cabina con texto muy claro sobre fondo muy oscuro, look que ya
       gustaba y se deja igual). En el resto de combinaciones (Sky claro,
       Choco ambos modos) currentColor quedaba demasiado sutil sobre botones
       de superficie más plana. var(--bg) se probó primero pero es casi
       idéntico a --surface (contraste ~1.15:1, invisible); var(--text) da
       8-18:1 de contraste garantizado contra --surface en los 4 skin+modo,
       así que es la variable real que asegura verse. */
    --hold-fill-color: currentColor;
}

.hold-confirm-button::before {
    content: '';
    position: absolute;
    inset: 0;
    /* Antes blanco fijo (rgba(255,255,255,.4)): pensado para botones de
       fondo saturado/oscuro (glassmorphism) -- sobre superficies más planas
       (Sky claro, Choco) un blanco translúcido casi no se distinguía del
       propio fondo. Ahora usa --hold-fill-color (ver arriba: currentColor
       solo en Sky oscuro, var(--bg) en el resto), con un borde de avance
       sólido a modo de "línea de nivel" para que el límite del relleno se
       note aunque el tono de fondo y relleno sean parecidos. */
    background: color-mix(in srgb, var(--hold-fill-color) 55%, transparent);
    border-top: 2px solid var(--hold-fill-color);
    transform: scaleY(0);
    transform-origin: bottom;
    transition: transform 0s linear;
    z-index: 0;
    pointer-events: none;
}

.hold-confirm-button.is-holding::before {
    transform: scaleY(1);
    transition-duration: var(--hold-confirm-duration, 5000ms);
    transition-timing-function: linear;
}

/* Variante rectangular, para reutilizar el hold-to-confirm en botones de
   administración normales (p. ej. "Borrar usuario"), en vez de la burbuja
   circular pensada para los botones grandes de fichaje. El relleno avanza
   de izquierda a derecha en lugar de de abajo hacia arriba. */
.hold-confirm-button--rect {
    width: auto;
    height: auto;
    border-radius: var(--radius);
    border-width: 1px;
    box-shadow: var(--shadow-soft);
}

.hold-confirm-button--rect::before {
    /* Avanza en horizontal, así que la "línea de nivel" va a la derecha del
       relleno (borde vertical), no arriba (eso sería para el avance en Y de
       la variante circular). */
    border-top: 0;
    border-right: 2px solid var(--hold-fill-color);
    transform: scaleX(0);
    transform-origin: left;
}

.hold-confirm-button--rect.is-holding::before {
    transform: scaleX(1);
}

.hold-confirm-button__label {
    position: relative;
    z-index: 1;
}

.hold-confirm-button__label small,
.hold-confirm-button__hold-hint {
    position: relative;
    z-index: 1;
    display: block;
    font-size: 0.68rem;
    font-weight: 500;
    opacity: 0.85;
}

.button--icon {
    gap: 6px;
}

.button--icon__icon {
    width: 16px;
    height: 16px;
    flex: 0 0 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.button--icon__icon svg {
    width: 16px;
    height: 16px;
    display: block;
}

.input {
    width: 100%;
    min-height: 46px;
    padding: 12px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--input-bg);
    color: var(--text);
    transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}

.input:hover:not(:disabled):not([readonly]) {
    border-color: var(--border-strong);
}

.input:disabled,
.input[readonly] {
    background-color: var(--input-bg-disabled);
    color: var(--text-soft);
    /* Chrome atenua los campos deshabilitados con su propio color/opacidad y
       los dejaba casi ilegibles en modo oscuro: se fuerza el color del tema
       (contraste >= 7:1 en oscuro). */
    opacity: 1;
    -webkit-text-fill-color: var(--text-soft);
}

.input:focus {
    outline: 2px solid color-mix(in srgb, var(--primary) 14%, transparent);
    border-color: var(--primary);
    background-color: var(--input-bg-focus);
}

select.input {
    appearance: none;
    background-image:
        linear-gradient(45deg, transparent 50%, var(--text-soft) 50%),
        linear-gradient(135deg, var(--text-soft) 50%, transparent 50%);
    background-position:
        calc(100% - 18px) calc(50% - 2px),
        calc(100% - 12px) calc(50% - 2px);
    background-size: 6px 6px, 6px 6px;
    background-repeat: no-repeat;
    padding-right: 36px;
}

/* Desplegables nativos (lista de opciones) en TODOS los skins y modos: la
   lista usaba los colores por defecto del navegador, que en modo oscuro no
   casaban con el tema (fondo gris del sistema, texto de otro contraste,
   y en los selects con fondo translúcido directamente transparentes). Se
   pintan con colores opacos del tema: superficie elevada + texto principal,
   la opción marcada con un tinte de la marca y las deshabilitadas atenuadas. */
select option,
select optgroup {
    background-color: var(--surface-elevated);
    color: var(--text);
}

select option:checked {
    background-color: color-mix(in srgb, var(--primary) 22%, var(--surface-elevated));
    color: var(--text);
}

select option:disabled {
    color: var(--text-soft);
}

label:has(> .input[required]) > span::after,
label:has(> input[required]) > span::after,
label:has(> select[required]) > span::after,
label:has(> textarea[required]) > span::after {
    content: '*';
    display: inline-block;
    margin-left: 4px;
    color: var(--danger-soft);
    font-weight: 700;
    line-height: 1;
    vertical-align: top;
}

.status {
    margin: 12px 0 0;
    font-size: 0.95rem;
}

.status:empty {
    display: none;
}

.status--error {
    color: var(--danger);
}

.status--success {
    color: var(--success);
}

.status--warning {
    color: var(--warning);
}

.badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    border: 1px solid transparent;
    border-radius: var(--radius-lg);
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    white-space: nowrap;
}

.badge--success {
    background: rgba(31, 143, 95, 0.12);
    border-color: rgba(31, 143, 95, 0.22);
    color: var(--success);
}

.badge--warning {
    background: var(--warning-soft);
    border-color: var(--warning-border);
    color: var(--warning);
}

.badge--danger {
    background: rgba(192, 57, 43, 0.12);
    border-color: rgba(192, 57, 43, 0.2);
    color: var(--danger);
}

.badge--neutral {
    background: rgba(100, 116, 139, 0.12);
    border-color: rgba(100, 116, 139, 0.22);
    color: var(--text-soft);
}

body[data-modal-open='true'] {
    overflow: hidden;
}

.app-modal-host {
    position: fixed;
    inset: 0;
    z-index: 2200;
    pointer-events: none;
}

.app-modal-layer {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    padding: 24px;
    pointer-events: auto;
}

.app-modal__backdrop {
    position: absolute;
    inset: 0;
    background: var(--modal-backdrop);
    backdrop-filter: blur(6px);
}

.app-modal {
    position: relative;
    width: min(var(--app-modal-width, 680px), calc(100vw - 32px));
    max-height: calc(100vh - 48px);
    display: grid;
    grid-template-rows: auto 1fr auto;
    background: var(--surface);
    border: 1px solid var(--modal-border);
    box-shadow: 0 28px 64px rgba(15, 23, 42, 0.22);
}

.app-modal__header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px;
    padding: 22px 24px 18px;
    border-bottom: 1px solid var(--modal-border);
    background: var(--modal-header-bg);
}

.app-modal__copy {
    display: grid;
    gap: 6px;
}

.app-modal__title,
.app-modal__description,
.app-modal__message {
    margin: 0;
}

.app-modal__title {
    font-size: 1.2rem;
    letter-spacing: -0.02em;
}

.app-modal__description {
    color: var(--text-soft);
    line-height: 1.6;
}

.app-modal__close {
    min-width: 92px;
}

.app-modal__body {
    padding: 24px;
    overflow: auto;
}

.app-modal__footer {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    flex-wrap: wrap;
    padding: 18px 24px 24px;
    border-top: 1px solid var(--modal-border);
    background: var(--modal-footer-bg);
}

.app-modal__message {
    line-height: 1.7;
}

/* ---- Switch reutilizable (p. ej. árbol de permisos) ---- */
.app-switch {
    display: inline-flex;
    align-items: center;
    gap: 0;
    cursor: pointer;
    user-select: none;
    flex: 0 0 auto;
}

.app-switch input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.app-switch__track {
    position: relative;
    width: 34px;
    height: 20px;
    border-radius: var(--radius);
    background: var(--border);
    transition: background 0.15s ease;
    flex: 0 0 auto;
}

.app-switch__track::after {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.3);
    transition: transform 0.15s ease;
}

.app-switch input:checked + .app-switch__track {
    background: var(--success, #1f8f5f);
}

.app-switch input:checked + .app-switch__track::after {
    transform: translateX(14px);
}

.app-switch input:disabled + .app-switch__track {
    opacity: 0.5;
    cursor: not-allowed;
}

.app-switch input:focus-visible + .app-switch__track {
    outline: 2px solid var(--success, #1f8f5f);
    outline-offset: 2px;
}

/* Estado "override": el valor difiere del que daría el rol por defecto. */
.app-switch--overridden .app-switch__track {
    box-shadow: 0 0 0 2px var(--warning-soft);
}

/* ---- Árbol de permisos (módulo > submódulo > acción) ---- */
.perm-tree {
    display: flex;
    flex-direction: column;
    gap: 22px;
}

.perm-tree__category {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.perm-tree__category-title {
    margin: 0;
    padding-bottom: 4px;
    border-bottom: 2px solid var(--border-strong);
    font-size: 0.72rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-soft);
}

.perm-tree__category-modules {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.perm-tree__module {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    overflow: hidden;
}

.perm-tree__module-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    width: 100%;
    padding: 10px 14px;
    background: var(--surface-soft);
    border: none;
    border-bottom: 1px solid var(--border);
    cursor: pointer;
    font-weight: 700;
    font-size: 0.88rem;
    color: var(--text);
    text-align: left;
}

.perm-tree__module-header:hover {
    background: var(--surface-hover);
}

.perm-tree__module-count {
    font-weight: 600;
    font-size: 0.72rem;
    color: var(--text-soft);
    white-space: nowrap;
}

.perm-tree__module-chevron {
    transition: transform 0.15s ease;
    flex: 0 0 auto;
    color: var(--text-soft);
}

.perm-tree__module.is-collapsed .perm-tree__module-chevron {
    transform: rotate(-90deg);
}

.perm-tree__module.is-collapsed .perm-tree__body {
    display: none;
}

.perm-tree__body {
    padding: 6px 14px 10px;
}

.perm-tree__submodule {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px 18px;
    padding: 8px 0;
    border-bottom: 1px solid rgba(207, 216, 230, 0.5);
}

.perm-tree__submodule:last-child {
    border-bottom: none;
}

.perm-tree__submodule-title {
    grid-column: 1 / -1;
    font-size: 0.76rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-soft);
    margin: 0 0 6px;
}

.perm-tree__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 7px 9px;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: var(--surface);
    min-width: 0;
}

@media (max-width: 900px) {
    .perm-tree__submodule {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 620px) {
    .perm-tree__submodule {
        grid-template-columns: 1fr;
    }
}

.perm-tree__row:hover {
    background: var(--surface-hover);
}

.perm-tree__row-label {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.perm-tree__row-icon {
    flex: 0 0 auto;
    width: 15px;
    height: 15px;
    display: inline-flex;
    color: var(--success, #1f8f5f);
}

.perm-tree__row-icon svg {
    width: 100%;
    height: 100%;
    display: block;
}

.perm-tree__row-icon--view {
    color: var(--primary, #1d4ed8);
}

.perm-tree__row-icon--delete {
    color: var(--danger, #c0392b);
}

.perm-tree__row-text {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.perm-tree__row-name {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text);
}

.perm-tree__row-meta {
    font-size: 0.68rem;
    color: var(--text-soft);
}

.perm-tree__row-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
}

.perm-tree__search {
    margin-bottom: 10px;
}

/* En escritorio, la tarjeta de Fichajes (Diseños 1-5) se muestra centrada
   con un ancho Y alto fijos tipo móvil -- mismo patrón ya usado en el
   dashboard de Logística del trabajador (.logistics-self-vehicle-banner/
   .logistics-self-tiles, max-width:480px + margin:0 auto), pedido
   explícito de aplicar aquí también ("mostralo en pequeño... con un
   ancho que más o menos sería un móvil", luego "dale a todos los skins
   el mismo ancho y largo"). Acotado EXPLÍCITAMENTE a la pestaña
   "fichajes" con [data-labor-tab-value="fichajes"] -- pedido explícito de
   no tocar Historial/Solicitudes/Ausencias, que deben poder seguir
   creciendo a lo alto con su contenido real (listas de longitud
   variable) en vez de quedar recortadas a un alto fijo de móvil.
   En el propio móvil (@media max-width:720px más abajo) sigue ocupando
   el 100% real, sin este límite. */
@media (min-width: 721px) {
    .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit {
        width: 480px !important;
        max-width: 480px !important;
        height: 780px !important;
        max-height: 780px !important;
        margin-left: auto !important;
        margin-right: auto !important;
        overflow-y: auto;
    }

    /* Historial/Solicitudes/Ausencias del trabajador: mismo ancho tipo
       móvil, centrado, PERO sin alto fijo -- pedido explícito ("esto
       siempre se verá en móviles o casi siempre, así que simularemos el
       ancho del móvil igual que hacemos en fichajes, pero respetaremos el
       alto en todas las pestañas historial solicitudes y ausencias"). Cada
       <section> de esas pestañas se centra con su alto natural, creciendo
       libremente según su contenido real (listas de longitud variable). */
    .labor-tabs__panel[data-labor-tab-value="historial"] .labor-tab-stack > .labor-card-section,
    .labor-tabs__panel[data-labor-tab-value="solicitudes"] .labor-tab-stack > .labor-card-section,
    .labor-tabs__panel[data-labor-tab-value="ausencias"] .labor-tab-stack > .labor-card-section {
        width: 480px !important;
        max-width: 480px !important;
        margin-left: auto !important;
        margin-right: auto !important;
    }
}

/* ============================================================
 * Cuadrados de acción del panel de fichaje (Fichar, Solicitar cambio de
 * turno, Solicitar fichaje, Teletrabajo, Ubicación, pausas). Antes este
 * rediseño completo (botones circulares por --clock-btn, fila centrada de
 * ancho fijo, tamaños escalonados por fila) vivía SOLO en el antiguo
 * theme.css, exclusivo del skin Blue ya eliminado -- Choco y Green se
 * quedaban con el rectángulo genérico 64x124px del CSS base del módulo,
 * mucho más pequeño y con otra forma. Bug real reportado: "los tamaños de
 * los cuadrados de fichaje no son iguales". Consolidado
 * aquí, sin escopar por skin, para que los 3 tengan el mismo tamaño/forma;
 * el color de cada botón lo sigue dando el CSS de módulo de cada skin. */
:root {
    --clock-btn: 64px;
}

/* :not([data-tc-variant-active]) -- pedido explícito: los subskins (2/3/4)
   controlan por completo su propio tamaño de botón (width/height), sin que
   este max-height/height !important genérico del Diseño 1 se lo pise (bug
   real reportado: "las piedras del Diseño 4 no se hacían más altas por más
   que subiera el height, porque este max-height las recortaba"). */
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-punch__button,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-punch__button.hold-confirm-button,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-side-button,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-side-button.hold-confirm-button,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-side-button--teletrabajo-day,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-side-button--location,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-side-button--teletrabajo-day.hold-confirm-button,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-side-button--location.hold-confirm-button,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-break__button {
    width: var(--clock-btn) !important;
    height: var(--clock-btn) !important;
    min-width: var(--clock-btn) !important;
    max-width: var(--clock-btn) !important;
    min-height: var(--clock-btn) !important;
    max-height: var(--clock-btn) !important;
    aspect-ratio: 1 / 1 !important;
    flex: 0 0 var(--clock-btn) !important;
    padding: 8px 6px !important;
    border-radius: 3px !important;
    display: grid !important;
    align-content: center;
    justify-items: center;
    gap: 4px !important;
    text-align: center;
    box-sizing: border-box;
}
/* :not([data-tc-variant-active]) -- pedido explícito: los subskins (2/3/4)
   controlan por completo su propio contraste de texto/icono, sin heredar
   nada de aquí (antes esto se colaba con !important sobre lo que cada
   subskin definía, bug real reportado). */
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-punch__label,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-side-button__label,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-break__label {
    font-size: .8rem !important;
    line-height: 1.1 !important;
    text-align: center;
}
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-punch__icon,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-side-button__icon,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-break__icon { font-size: 1.4rem; line-height: 1; }
.timeclock-punch-row,
.timeclock-teletrabajo-actions,
.timeclock-breaks {
    display: flex !important;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 12px !important;
}
/* Botones del cockpit de Fichajes escalados a la altura REAL de pantalla
   (100dvh, que ya descuenta la barra de direcciones del navegador móvil,
   a diferencia de 100vh) -- pedido explícito: "totalmente ajustado a lo
   que dé el móvil verticalmente, sin tener que hacer scroll". clamp()
   permite que se encoja de forma fluida en móviles bajos (iPhone SE) y no
   se pase de 96px en los más altos, en vez de un valor fijo que puede
   sobrar o faltar según el modelo. */
@media (max-width: 720px) { :root { --clock-btn: clamp(56px, 11dvh, 96px); } }

/* Misma distribución en las 3: cada fila ocupa el mismo ancho total y sus botones se lo reparten a partes iguales */
:root { --clock-row-width: calc(3 * var(--clock-btn) + 2 * 12px); }
.timeclock-punch-row,
.timeclock-teletrabajo-actions,
.timeclock-breaks {
    width: var(--clock-row-width) !important;
    max-width: 100%;
    margin-left: auto !important;
    margin-right: auto !important;
    display: flex !important;
    flex-wrap: nowrap !important;
    gap: 12px !important;
}
.timeclock-punch__button,
.timeclock-punch__button.hold-confirm-button,
.timeclock-side-button,
.timeclock-side-button.hold-confirm-button,
.timeclock-side-button--teletrabajo-day,
.timeclock-side-button--location,
.timeclock-side-button--teletrabajo-day.hold-confirm-button,
.timeclock-side-button--location.hold-confirm-button,
.timeclock-break__button {
    width: auto !important;
    min-width: 0 !important;
    max-width: none !important;
    aspect-ratio: auto !important;
    flex: 1 1 0 !important;
}
.timeclock-punch-row-wrap { display: grid; gap: 12px; justify-items: center; }

/* Fichar más grande al centro, filas de abajo más bajas, todo centrado con el mismo ancho */
.timeclock-punch { max-width: none !important; width: 100% !important; }
.timeclock-punch-row-wrap { flex-direction: column !important; align-items: center !important; gap: 12px !important; }
.timeclock-punch-row,
.timeclock-teletrabajo-actions,
.timeclock-breaks {
    width: min(100%, 420px) !important;
    margin-left: auto !important;
    margin-right: auto !important;
}
.timeclock-punch-row { align-items: center !important; --clock-btn: 140px; }
.timeclock-punch-row .timeclock-punch__button { --clock-btn: 140px; flex: 1.3 1 0 !important; min-width: 0 !important; }
.timeclock-teletrabajo-actions { --clock-btn: 68px; }
.timeclock-breaks { --clock-btn: 92px; }
.timeclock-teletrabajo-actions .timeclock-side-button,
.timeclock-breaks .timeclock-break__button { grid-auto-flow: row; }
.timeclock-teletrabajo-actions .timeclock-side-button__icon,
.timeclock-breaks .timeclock-break__icon { font-size: 1.1rem; }
/* En móvil, --clock-btn: 140px/92px/68px fijos (arriba) no encogían con la
   fila (min-width:0 no basta si min-width:var(--clock-btn) !important del
   bloque genérico sigue ganando, línea ~1678) -- causaba que la fila de
   Fichar desbordara por la derecha en pantallas estrechas (bug real
   reportado: "en moviles no caben bien los skins, el subskin 1 se sale
   por la derecha"). Se acota igual que el resto del responsive. */
/* clamp() con dvh (no vh, que no descuenta la barra de direcciones del
   navegador móvil): estos tres tamaños escalan con la altura REAL
   disponible, para que la pestaña "Fichajes" quepa siempre sin scroll
   en cualquier móvil, en vez de un tamaño fijo que puede sobrar/faltar
   según el modelo -- pedido explícito ("totalmente ajustado a lo que dé
   el móvil verticalmente"). */
/* dvh (altura de VIEWPORT completo) es la causa real del bug reportado
   ("los botones de abajo se cortan"): un botón a "12dvh" se calcula sobre
   el 100% de la pantalla SIN saber cuánto ya ocupó el header encima --
   así que aunque el header reste espacio real (ver bloque flex más abajo,
   "TODA la cadena... flex-column"), el botón no se entera y sigue
   queriendo su tamaño basado en el dvh completo, sobresaliendo y
   quedando cortado por el overflow:hidden. Corregido: --clock-btn en
   unidades relativas al ANCHO del contenedor (no a la altura de
   viewport), y toda la fila usa flex real con min-height:0 para que su
   tamaño se derive del espacio que REALMENTE le queda tras el flex del
   header, nunca de un porcentaje de pantalla que lo ignora. */
@media (max-width: 720px) {
    .timeclock-punch-row-wrap {
        display: flex !important;
        flex-direction: column !important;
        min-height: 0;
        flex: 1 1 auto;
        justify-content: space-evenly !important;
        gap: 6px !important;
    }
    .timeclock-punch-row,
    .timeclock-teletrabajo-actions,
    .timeclock-breaks {
        flex: 0 1 auto;
        min-height: 0;
    }
    .timeclock-punch-row { --clock-btn: min(22vw, 92px); }
    .timeclock-punch-row .timeclock-punch__button { --clock-btn: min(22vw, 92px); }
    .timeclock-teletrabajo-actions { --clock-btn: min(15vw, 60px); margin-top: 0 !important; }
    .timeclock-breaks { --clock-btn: min(18vw, 76px); margin-top: 0 !important; }
}

.timeclock-break__button[hidden] { display: none !important; }

/* Botones de pausa (fondo amarillo/naranja claro en cualquier skin): texto e
   icono oscuros para contraste, no es un color de marca.
   :not([data-tc-variant-active]) -- pedido explícito: los subskins (2/3/4)
   controlan por completo su propio contraste de texto/icono, sin heredar
   nada de aquí. */
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-break__button,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-break__button .timeclock-break__label,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-break__button .timeclock-break__label-time,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-break__button .hold-confirm-button__hold-hint,
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-break__button small {
    color: #3b2a00 !important;
    text-shadow: none !important;
    opacity: 1;
}
.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-break__button .timeclock-break__icon { color: #3b2a00 !important; }

.timeclock-card--cockpit:not([data-tc-variant-active]) .timeclock-break__button .app-icon { filter: none !important; opacity: .85; }

/* ============================================================
 * Dashboard de administración laboral: tarjetas de alerta con altura
 * fija (salvo "Semana actual") + 2 columnas en móvil. Antes vivía solo
 * en el antiguo theme.css bajo el skin Blue ya eliminado (con 3 capas
 * "v1/v2/v3" acumuladas sin limpiar, de las que solo la última -- reproducida
 * aquí tal cual -- tenía efecto visual real) -- Choco y Green se quedaban sin
 * altura fija y en una sola columna en móvil, con tarjetas mucho más
 * largas que ese otro skin (bug real reportado con capturas comparativas).
 * Generalizado sin [data-skin] para que aplique a los 3 skins por igual.
 * ============================================================ */
.labor-sesame-card:not([data-labor-dashboard-card='week']) {
    height: 138px;
    grid-template-rows: auto minmax(0, 1fr);
    overflow: hidden;
}
.labor-sesame-card:not([data-labor-dashboard-card='week']) .labor-sesame-card__body {
    max-height: none;
    min-height: 0;
    height: 100%;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: thin;
}
.labor-sesame-card:not([data-labor-dashboard-card='week']) .labor-sesame-card__body > * {
    min-height: 0;
}
.labor-sesame-card:not([data-labor-dashboard-card='week']) .labor-whosin-avatars {
    flex-wrap: nowrap;
    overflow-x: auto;
}

@media (max-width: 720px) {
    .labor-sesame-card:not([data-labor-dashboard-card='week']) {
        height: 130px;
    }
}

@media (max-width: 899px) {
    /* El elemento real lleva las dos clases a la vez
       (.labor-dashboard-grid.labor-dashboard-grid--sesame, ver labor.html):
       .labor-dashboard-grid pone display:grid SIEMPRE (fuera de cualquier
       media query), y como ese archivo de skin se carga DESPUÉS de este
       base.css, ganaba a flex-direction/flex-wrap de aquí -- que no tienen
       ningún efecto sin display:flex. El contenedor se quedaba en modo grid
       con columnas de min 260px mientras los hijos tenían width:calc(50%...)
       pensado para flexbox, dando overflow horizontal (bug real reportado:
       "todos los skins se ven descuadrados en móvil, todo cortado"). Forzar
       display:flex aquí con !important corrige la causa raíz. */
    .labor-dashboard-grid--sesame {
        display: flex !important;
        flex-direction: row !important;
        flex-wrap: wrap;
    }
    .labor-dashboard-grid--sesame > .labor-sesame-card {
        width: calc(50% - 3px);
        flex: 0 0 calc(50% - 3px);
    }
    .labor-dashboard-grid--sesame > .labor-sesame-card[data-labor-dashboard-card='week'] {
        width: 100%;
        flex-basis: 100%;
    }
}


/* =====================================================================
   RESPONSIVE -- ajustes de layout general en pantallas pequeñas. Antes
   vivía en base.responsive.css, archivo separado -- fusionado aquí a
   petición explícita: un único base.css, sin más archivos sueltos que
   los ya propios de cada skin.
   ===================================================================== */

@media (max-width: 980px) {
    .app-shell,
    .app-topbar__inner {
        width: min(96vw, 1680px);
    }

    body[data-authenticated='true'][data-sidebar-open='true'] .app-shell__layout {
        grid-template-columns: 224px minmax(0, 1fr);
    }

    .app-sidebar__panel {
        width: 224px;
        --sb-top: 10px;
        --sb-right: 10px;
    }
}

@media (max-width: 720px) {
    :root {
        --topbar-height: 68px;
    }

    .app-topbar {
        /* Antes azul marino fijo (rgba(15,23,42,.92) + borde rgba(96,165,250,...)):
           este archivo se carga siempre, sin depender del skin activo, así
           que pisaba el degradado de marca (var(--topbar-gradient), correcto
           en escritorio) con el mismo azul en los 3 skins en móvil -- bug
           real reportado ("en móviles el menú se ve azul en todos los
           skins"). Usa las mismas variables que el escritorio. */
        background: var(--topbar-gradient);
        border-bottom-color: rgba(255, 255, 255, 0.14);
        box-shadow: 0 14px 34px rgba(15, 23, 42, 0.28);
    }

    /* Botones más compactos pero tocables, en los 3 skins por igual: este
       ajuste solo existía en el antiguo theme.css (exclusivo del skin Blue
       ya eliminado), así que en Choco/Green los botones se quedaban en
       38px/32px (más grandes que en ese otro skin) en el mismo viewport --
       bug real reportado ("los tamaños de los botones no son iguales en los
       tres modos"). */
    .button {
        min-height: 34px;
        padding: 0 8px;
    }
    .button--small {
        min-height: 28px;
    }
    /* Mismo motivo que .button arriba: solo existía en el antiguo theme.css (skin Blue ya eliminado). */
    input:not([type='checkbox']):not([type='radio']),
    select {
        min-height: 34px;
        padding: 4px 8px;
    }

    .app-shell {
        width: calc(100vw - 20px);
        padding: 18px 0 30px;
    }

    .app-shell__layout {
        display: block;
    }

    .app-sidebar {
        position: fixed;
        top: var(--topbar-height);
        left: 0;
        bottom: 0;
        width: min(84vw, 280px);
        overflow: visible;
        opacity: 1;
        transform: translateX(calc(-100% - 16px));
        transition: transform 0.22s ease;
        z-index: 990;
    }

    body[data-authenticated='true'][data-sidebar-open='true'] .app-sidebar {
        transform: translateX(0);
    }

    .app-sidebar__panel {
        position: relative;
        top: 0;
        width: 100%;
        height: 100%;
        --sb-top: 14px;
        --sb-right: 14px;
        padding: 14px 14px 20px;
        border-left: 0;
        border-radius: 0 3px 3px 0;
        overflow-y: auto;
        box-shadow: 0 20px 44px rgba(15, 23, 42, 0.22);
    }

    .app-shell__overlay {
        position: fixed;
        inset: var(--topbar-height) 0 0 0;
        z-index: 980;
        display: block;
        margin: 0;
        padding: 0;
        border: 0;
        background: rgba(15, 23, 42, 0.3);
        cursor: pointer;
    }

    .app-topbar__inner {
        width: calc(100vw - 20px);
        min-height: auto;
        padding: 10px 0;
        align-items: center;
        gap: 12px;
    }

    .app-topbar__session,
    .app-topbar__identity,
    .app-topbar__profile,
    .app-topbar__profile-copy {
        min-width: 0;
    }

    .app-topbar__identity,
    .app-topbar__profile {
        gap: 10px;
    }

    .app-topbar__profile {
        align-items: center;
    }

    .app-topbar__avatar {
        width: 44px;
        height: 44px;
        flex-basis: 44px;
        border-color: rgba(255, 255, 255, 0.24);
        box-shadow: 0 8px 18px rgba(15, 23, 42, 0.24);
    }

    .app-topbar__name {
        font-size: 1rem;
        line-height: 1.15;
    }

    /* Antes azul fijo (rgba(191,219,254,...) texto, rgba(96,165,250,...)/
       rgba(37,99,235,...) fondo/borde de los 2 botones): igual que el fondo
       de la topbar de arriba, esto vive sobre el degradado de marca
       (var(--topbar-gradient)) en CUALQUIER skin -- un azul fijo desentonaba
       en Choco/Green. Blanco translúcido funciona igual de bien sobre
       cualquier color de fondo, coherente con el resto de estados sobre la
       topbar (ver base.css, incluida la solución ya aplicada para el mismo
       problema en el toggle del sidebar). */
    .app-topbar__role {
        font-size: 0.82rem;
        line-height: 1.2;
        color: rgba(255, 255, 255, 0.85);
    }

    .app-topbar__logout.button--secondary {
        width: 44px;
        min-width: 44px;
        flex-basis: 44px;
        border-color: rgba(255, 255, 255, 0.3);
        background: rgba(255, 255, 255, 0.14);
    }

    .app-topbar__menu-toggle.button--secondary {
        width: 44px;
        min-width: 44px;
        flex-basis: 44px;
        border-color: rgba(255, 255, 255, 0.3);
        background: rgba(255, 255, 255, 0.14);
    }

    .app-modal-layer {
        padding: 16px;
    }

    .app-modal {
        width: min(var(--app-modal-width, 680px), calc(100vw - 24px));
        max-height: calc(100vh - 32px);
        /* Antes azul fijo (rgba(191,219,254,...)): el modal ya tiene su
           propio var(--modal-border) por skin+modo, correcto en escritorio;
           en móvil se pisaba con un azul fijo, desentonando en Choco/Green. */
        border-color: var(--modal-border);
        box-shadow: 0 28px 60px rgba(15, 23, 42, 0.24);
    }

    .app-modal__header,
    .app-modal__body,
    .app-modal__footer {
        padding-left: 20px;
        padding-right: 20px;
    }

    .app-modal__header,
    .app-modal__footer {
        display: grid;
        gap: 12px;
    }

    .app-modal__header {
        padding-top: 20px;
        padding-bottom: 16px;
    }

    .app-modal__body {
        padding-top: 20px;
        padding-bottom: 20px;
    }

    .app-modal__footer {
        padding-top: 14px;
        padding-bottom: 20px;
    }

    .app-modal__title {
        font-size: 1.08rem;
    }

    .app-modal__close,
    .app-modal__footer .button {
        width: 100%;
    }

    .button--icon {
        width: 46px;
        min-width: 46px;
        padding: 0;
    }

    .button--icon__label {
        display: none;
    }
}

@media (max-width: 560px) {
    :root {
        --topbar-height: 60px;
    }

    .app-shell {
        width: calc(100vw - 16px);
        padding: 14px 0 26px;
    }

    .app-sidebar {
        width: min(86vw, 264px);
    }

    .app-topbar__inner {
        width: calc(100vw - 16px);
        padding: 8px 0;
        gap: 8px;
    }

    .app-topbar__identity,
    .app-topbar__profile {
        gap: 8px;
    }

    .app-topbar__avatar {
        width: 40px;
        height: 40px;
        flex-basis: 40px;
    }

    .app-topbar__name {
        font-size: 0.92rem;
    }

    .app-topbar__role {
        font-size: 0.76rem;
    }

    .app-topbar__profile-copy {
        gap: 1px;
    }

    .app-topbar__logout.button--secondary {
        width: 40px;
        min-width: 40px;
        flex-basis: 40px;
    }

    .app-topbar__menu-toggle.button--secondary {
        width: 40px;
        min-width: 40px;
        flex-basis: 40px;
    }

    .app-topbar__menu-icon svg,
    .app-topbar__logout-icon svg {
        width: 18px;
        height: 18px;
    }

    .app-modal-layer {
        padding: 12px;
    }

    .app-modal {
        width: min(var(--app-modal-width, 680px), calc(100vw - 16px));
        max-height: calc(100vh - 24px);
    }

    .app-modal__header,
    .app-modal__body,
    .app-modal__footer {
        padding-left: 16px;
        padding-right: 16px;
    }

    .app-modal__header {
        gap: 10px;
    }

    /* Choco (choco) en móvil: aún más compacto que el resto de skins, a
       petición explícita ("compacto nivel extremo"). [data-skin='choco']
       eleva la especificidad por encima de .button/.input genéricos de
       este mismo media query, así que no hace falta !important. */
    [data-skin='choco'] .button {
        min-height: 28px;
        padding: 0 8px;
    }

    [data-skin='choco'] input:not([type='checkbox']):not([type='radio']),
    [data-skin='choco'] select,
    [data-skin='choco'] .input {
        min-height: 30px;
        padding: 5px 8px;
    }

    [data-skin='choco'] .app-modal__header,
    [data-skin='choco'] .app-modal__body,
    [data-skin='choco'] .app-modal__footer {
        padding-left: 10px;
        padding-right: 10px;
    }

    /* Green (green) es clon estructural de Choco: mismo bloque en móvil. */
    [data-skin='green'] .button {
        min-height: 28px;
        padding: 0 8px;
    }

    [data-skin='green'] input:not([type='checkbox']):not([type='radio']),
    [data-skin='green'] select,
    [data-skin='green'] .input {
        min-height: 30px;
        padding: 5px 8px;
    }

    [data-skin='green'] .app-modal__header,
    [data-skin='green'] .app-modal__body,
    [data-skin='green'] .app-modal__footer {
        padding-left: 10px;
        padding-right: 10px;
    }

    /* Sky (sky) en móvil: se basa en Choco y comparte su misma densidad
       "compacto nivel extremo", así que replica el mismo bloque. */
    [data-skin='sky'] .button {
        min-height: 28px;
        padding: 0 8px;
    }

    [data-skin='sky'] input:not([type='checkbox']):not([type='radio']),
    [data-skin='sky'] select,
    [data-skin='sky'] .input {
        min-height: 30px;
        padding: 5px 8px;
    }

    [data-skin='sky'] .app-modal__header,
    [data-skin='sky'] .app-modal__body,
    [data-skin='sky'] .app-modal__footer {
        padding-left: 10px;
        padding-right: 10px;
    }
}

/* Logística en móvil: menús solo con iconos, en una línea. Antes vivía solo
   en el antiguo theme.css (exclusivo del skin Blue ya eliminado) -- Choco y
   Green se quedaban con el texto completo desbordando la barra (bug real
   reportado con captura). Generalizado aquí sin [data-skin] para que
   aplique a los 3 skins. */
@media (max-width: 720px) {
    [data-logistics-admin-tab] .logistics-tab-text,
    [data-labor-admin-main-tab] .logistics-tab-text,
    [data-labor-tabs^="logistics-"] .labor-tab-label {
        display: none !important;
    }
    [aria-label="Secciones de logística"],
    [aria-label="Secciones de administración laboral"] {
        display: grid !important;
        grid-auto-flow: column;
        grid-auto-columns: minmax(0, 1fr);
        flex-wrap: nowrap !important;
    }
    [aria-label="Secciones de logística"] .labor-settings-tabs__item,
    [aria-label="Secciones de administración laboral"] .labor-settings-tabs__item {
        justify-content: center;
        font-size: 1.1rem !important;
        padding: 8px 4px !important;
        position: relative;
    }
    [data-labor-tabs^="logistics-"] > .labor-tabs__nav {
        display: grid !important;
        grid-auto-flow: column;
        grid-auto-columns: minmax(0, 1fr);
        grid-template-columns: none !important;
    }
    [data-labor-tabs^="logistics-"] .labor-tabs__button {
        font-size: 1.15rem !important;
        min-height: 38px !important;
    }
    .dress-garment-season-filter {
        display: grid !important;
        grid-auto-flow: column;
        grid-auto-columns: minmax(0, 1fr);
    }
    .dress-garment-season-filter__btn .logistics-tab-text {
        display: none;
    }
    .dress-garment-season-filter__btn {
        font-size: 1.1rem;
    }
}
/* ---- Campos obligatorios: sin asterisco (no ocupa espacio ni provoca saltos de línea) ---------------------------
   · Etiquetas: un puntito rojo de ancho cero junto al texto (.wh-required).
   · Cualquier campo obligatorio vacío lleva una franja roja a la izquierda, que desaparece al rellenarlo. */
.wh-required { display: inline-block; position: relative; width: 0; height: 0; overflow: visible; vertical-align: top; }
.wh-required::after { content: ''; position: absolute; left: 4px; top: 3px; width: 6px; height: 6px; border-radius: 3px; background: #dc2626; }
input.input:required:invalid,
select.input:required:invalid,
textarea.input:required:invalid { box-shadow: inset 3px 0 0 #dc2626; }

/* ======== Ventanas modernas: cabecera compacta, cierre en icono, entrada suave ======== */
.app-modal { border-top: 3px solid var(--primary); box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28), 0 2px 6px rgba(15, 23, 42, 0.12); animation: app-modal-in .18s ease-out; }
@keyframes app-modal-in { from { opacity: 0; transform: translateY(10px) scale(.985); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .app-modal { animation: none; } }
.app-modal__header { align-items: center; gap: 12px; padding: 12px 18px; }
.app-modal__copy { gap: 2px; min-width: 0; }
.app-modal__title { font-size: 1.02rem; font-weight: 800; letter-spacing: -0.01em; }
.app-modal__description { font-size: .8rem; line-height: 1.4; }
.app-modal__body { padding: 16px 18px; }
.app-modal__footer { padding: 10px 18px; gap: 8px; }
.app-modal__footer .button { min-height: 36px; padding: 0 18px; }
.app-modal__close { min-width: 0; width: 32px; height: 32px; min-height: 0; padding: 0; font-size: 0; flex: none; }
.app-modal__close::before { content: '✕'; font-size: .95rem; line-height: 1; }
.app-modal .app-modal__close { font-size: 0 !important; min-width: 0 !important; width: 32px; height: 32px; min-height: 0 !important; padding: 0 !important; gap: 0; display: inline-flex; align-items: center; justify-content: center; }
.app-modal .app-modal__close::before { font-size: .95rem; }

/* Fichar en móvil: pantalla fija. Sin rebote ni arrastre vertical (ni de la página ni del propio panel). */
@media (max-width: 720px) {
    html:has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])),
    body:has(.labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden])) {
        overscroll-behavior: none;
    }

    .labor-tabs__panel[data-labor-tab-value="fichajes"]:not([hidden]) .timeclock-card--cockpit {
        touch-action: none;
        overscroll-behavior: none;
    }
}

/* ============================================================
 * FICHAR EN MÓVIL: ESQUELETO ÚNICO PARA LOS TRES DISEÑOS
 * Los diseños (1, 2 y 3) solo deben cambiar de ASPECTO (colores, formas, tipografía, decoración), nunca de reparto ni de
 * tamaño: misma altura de tarjeta (la fija timeclock.js) y mismas filas con las mismas proporciones. Todo se mide en cqh/cqw
 * (unidades del propio contenedor: la tarjeta), así que escala igual en cualquier móvil. Va con selector largo y !important
 * a propósito: tiene que ganar a los width/height propios que trae cada diseño..
 * ============================================================ */
@media (max-width: 720px) {
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit {
        container-type: size;
        container-name: tcc;
        margin-top: 0 !important;
        margin-bottom: 0 !important;
        padding: 12px 10px !important;
        clip-path: inset(0);
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .labor-card-section__body {
        display: flex !important;
        flex-direction: column !important;
        justify-content: space-between !important;
        gap: 0 !important;
        padding: 8px !important;
    }

    /* Reloj */
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .tc-hud {
        flex: 0 0 auto !important;
        height: 26cqh !important;
        margin: 0 !important;
        padding: 0 8px !important;
        display: flex !important;
        flex-direction: column !important;
        align-items: center !important;
        justify-content: center !important;
        overflow: hidden !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .tc-hud__time { font-size: 2.1rem !important; line-height: 1.1 !important; }
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .tc-hud__date { font-size: 0.68rem !important; margin-top: 1cqh !important; }
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .tc-hud__company { font-size: max(0.6rem, 1.8cqh) !important; margin-top: 0.4cqh !important; }
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .tc-hud__state { font-size: 0.62rem !important; margin-top: 1cqh !important; padding-top: 0.3cqh !important; padding-bottom: 0.3cqh !important; }

    /* Normal / Horas extra / Teletrabajo */
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-kind-select:not([hidden]) { flex: 0 0 auto !important; height: 6.5cqh !important; margin: 0 !important; }
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-kind-select__options { height: 100% !important; margin: 0 !important; }
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-kind-select__option { height: 100% !important; margin: 0 !important; padding-top: 0 !important; padding-bottom: 0 !important; font-size: max(0.62rem, 1.9cqh) !important; display: flex !important; align-items: center !important; justify-content: center !important; }

    /* Zona de botones: columna que reparte el alto; cada fila tiene su alto proporcional */
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-punch {
        flex: 1 1 auto !important;
        min-height: 0 !important;
        display: flex !important;
        flex-direction: column !important;
        justify-content: space-evenly !important;
        gap: 1.6cqh !important;
        margin: 0 !important;
        padding: 0 4px !important;
        overflow: visible !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-punch-row-wrap {
        display: flex !important;
        flex-direction: column !important;
        gap: 1.6cqh !important;
        margin: 0 !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-punch-row {
        display: grid !important;
        grid-template-columns: 1fr 1.25fr 1fr !important;
        gap: 3cqw !important;
        height: 22cqh !important;
        align-items: stretch !important;
        margin: 0 !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-punch-row > .timeclock-side-button {
        width: 100% !important;
        height: 100% !important;
        min-width: 0 !important;
        max-width: none !important;
        min-height: 0 !important;
        max-height: none !important;
        margin: 0 !important;
    }

    /* El botón principal siempre cuadrado/redondo y centrado en su celda, con el mismo alto en los tres diseños */
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-punch-row > .timeclock-punch__button {
        height: 100% !important;
        width: auto !important;
        aspect-ratio: 1 / 1 !important;
        max-width: 100% !important;
        min-width: 0 !important;
        min-height: 0 !important;
        max-height: none !important;
        justify-self: center !important;
        margin: 0 !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-teletrabajo-actions:not([hidden]) {
        display: grid !important;
        grid-template-columns: 1fr 1fr !important;
        gap: 3cqw !important;
        height: 9.5cqh !important;
        margin: 0 !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-teletrabajo-actions .timeclock-side-button {
        width: 100% !important;
        height: 100% !important;
        min-width: 0 !important;
        max-width: none !important;
        min-height: 0 !important;
        max-height: none !important;
        margin: 0 !important;
        flex-direction: row !important;
        gap: 6px !important;
    }

    /* Pausas */
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-breaks {
        flex: 0 0 auto !important;
        display: grid !important;
        grid-auto-flow: column !important;
        grid-auto-columns: 1fr !important;
        gap: 3cqw !important;
        height: 10.5cqh !important;
        margin: 0 !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-breaks .timeclock-break__button {
        width: 100% !important;
        height: 100% !important;
        min-width: 0 !important;
        max-width: none !important;
        min-height: 0 !important;
        max-height: none !important;
        margin: 0 !important;
    }

    /* Textos de los botones proporcionales al alto, con un mínimo legible */
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-side-button__label,
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-break__label { font-size: max(0.56rem, 1.6cqh) !important; line-height: 1.15 !important; }
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-punch__label { font-size: max(0.7rem, 2.2cqh) !important; line-height: 1.1 !important; }
}

/* Fichar en móvil: el nombre de la empresa del reloj se pinta DESPUÉS de cargar y empujaba el contenido (el cálculo de alto ya
   estaba hecho sin él). Se oculta en móvil en los tres diseños. */
@media (max-width: 720px) {
    .labor-tabs__panel[data-labor-tab-value="fichajes"] .tc-hud__company {
        display: none !important;
    }
}

/* Fichar en móvil: contenido interno de los botones proporcional al alto, para que NADA se salga de su fila (en el diseño 3 las
   pausas llevan icono + 3 líneas y se desbordaban por abajo). Mismos tamaños en los tres diseños. */
@media (max-width: 720px) {
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-breaks .timeclock-break__button {
        display: flex !important;
        flex-direction: column !important;
        align-items: center !important;
        justify-content: center !important;
        gap: 0.3cqh !important;
        padding: 0.4cqh 2px !important;
        overflow: hidden !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-break__icon {
        width: 3.8cqh !important;
        height: 3.8cqh !important;
        min-height: 0 !important;
        font-size: 2.2cqh !important;
        line-height: 1 !important;
        margin: 0 !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-break__label,
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-break__label-time {
        font-size: max(0.5rem, 1.35cqh) !important;
        line-height: 1.1 !important;
        margin: 0 !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-breaks .hold-confirm-button__hold-hint {
        font-size: max(0.46rem, 1.2cqh) !important;
        line-height: 1 !important;
        margin: 0 !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-side-button,
    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-punch__button {
        overflow: hidden !important;
        padding: 0.4cqh 2px !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-side-button__icon {
        width: 4.6cqh !important;
        height: 4.6cqh !important;
        min-height: 0 !important;
        font-size: 2.6cqh !important;
        margin: 0 !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-punch__icon {
        font-size: 4cqh !important;
        line-height: 1 !important;
    }
}

/* ============================================================
 * FICHAR EN MÓVIL: ALTO DE LA TARJETA SOLO CON CSS (igual en los tres diseños, sin JavaScript)
 * La tarjeta ocupa en pantalla desde justo debajo de la cabecera hasta justo encima de la barra de abajo. Arriba y abajo se
 * fijan con top/bottom, así que el alto = alto real de la pantalla menos esas franjas: se adapta a cualquier móvil.
 * Las franjas (cabecera, barra de 4 botones y pie) tienen alto explícito aquí para que el cálculo sea exacto.
 * ============================================================ */
@media (max-width: 720px) {
    :root {
        --tc-nav-h: 60px;
    }

    html body[data-authenticated='true'] [data-labor-tabs="timeclock"] > .labor-tabs__nav {
        box-sizing: border-box !important;
        height: calc(var(--tc-nav-h) + env(safe-area-inset-bottom, 0px)) !important;
        min-height: 0 !important;
        padding-top: 0 !important;
        padding-bottom: env(safe-area-inset-bottom, 0px) !important;
        align-items: stretch !important;
    }

    html body[data-authenticated='true'] [data-labor-tabs="timeclock"] > .labor-tabs__nav > .labor-tabs__button {
        min-height: 0 !important;
        height: auto !important;
    }

    html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit {
        position: fixed !important;
        left: 0 !important;
        right: 0 !important;
        top: calc(var(--topbar-height) + 4px) !important;
        bottom: calc(var(--footer-height, 0px) + var(--tc-nav-h) + env(safe-area-inset-bottom, 0px) + 4px) !important;
        width: auto !important;
        max-width: none !important;
        height: auto !important;
        min-height: 0 !important;
        max-height: none !important;
        margin: 0 !important;
        box-sizing: border-box !important;
        z-index: 5 !important;
    }
}

/* Ausencias en móvil: ocupa todo el ancho disponible (sin los márgenes y rellenos de la página ni de las tarjetas). */
@media (max-width: 720px) {
    body[data-authenticated='true']:has(.labor-tabs__panel[data-labor-tab-value="ausencias"]:not([hidden])) .app-shell {
        width: 100vw;
        max-width: 100vw;
    }

    body[data-authenticated='true']:has(.labor-tabs__panel[data-labor-tab-value="ausencias"]:not([hidden])) .labor-panel__body {
        padding: 4px 0 !important;
    }

    body[data-authenticated='true']:has(.labor-tabs__panel[data-labor-tab-value="ausencias"]:not([hidden])) .labor-tabs__panel[data-labor-tab-value="ausencias"] .labor-tab-stack > .labor-card-section {
        width: 100% !important;
        max-width: none !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding: 8px 4px !important;
        border-left: 0 !important;
        border-right: 0 !important;
        border-radius: 0 !important;
    }

    body[data-authenticated='true']:has(.labor-tabs__panel[data-labor-tab-value="ausencias"]:not([hidden])) .labor-tabs__panel[data-labor-tab-value="ausencias"] .labor-leave-calendar {
        width: 100%;
        max-width: none;
    }
}

/* La "i" de información (mensajes del día) en móvil va más arriba, bajo la cabecera: en el centro de la pantalla coincidía con
   los botones flotantes de enviar vacaciones/ausencias al marcar un día. */
@media (max-width: 720px) {
    .timeclock-messages-info--floating {
        top: calc(var(--topbar-height) + 72px);
        transform: none;
    }
}

/* Los tres diseños de Fichar: 8px de aire interior en todos los lados del contenido (móvil y escritorio). */
.labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit > .labor-card-section__body {
    padding: 8px;
}

/* Diseño 2: sin tornillos (se quitan los dos círculos de las esquinas de arriba). */
html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit.timeclock-card--v2::before,
html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit.timeclock-card--v2::after {
    content: none !important;
    display: none !important;
}

/* Contenedores cuadrados de Fichar (tarjeta, reloj, botones laterales, teletrabajo/ubicación y pausas): esquinas casi rectas
   en los tres diseños. El botón principal redondo y las píldoras de Normal/Horas extra/Teletrabajo no se tocan. */
html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit,
html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .tc-hud,
html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-side-button,
html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit .timeclock-break__button {
    border-radius: 3px !important;
}

/* Diseño 3: todos los botones llevan un borde de 1px del color de marca del skin principal elegido (Choco/Green/Sky).
   Los botones rectangulares (pausas) usan un border normal. Los que tienen forma recortada (el "tejado" de los laterales y el
   octógono del principal) no pueden: un border se corta en los lados diagonales. Para esos, el contorno se dibuja en el
   CONTENEDOR con drop-shadow, que se aplica DESPUÉS del recorte y por tanto sigue la forma exacta. */
html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit.timeclock-card--v3 .timeclock-break__button {
    border: 1px solid var(--brand-400) !important;
    box-sizing: border-box !important;
}

html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit.timeclock-card--v3 .timeclock-side-button,
html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit.timeclock-card--v3 .timeclock-punch__button {
    border: none !important;
}

html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit.timeclock-card--v3 .timeclock-punch-row,
html body[data-authenticated='true'] .labor-tabs__panel[data-labor-tab-value="fichajes"] .timeclock-card--cockpit.timeclock-card--v3 .timeclock-teletrabajo-actions {
    filter:
        drop-shadow(1px 0 0 var(--brand-400))
        drop-shadow(-1px 0 0 var(--brand-400))
        drop-shadow(0 1px 0 var(--brand-400))
        drop-shadow(0 -1px 0 var(--brand-400));
}

/* Fichajes en móvil: los modales dejan un poco de margen a los lados en vez de ocupar todo el ancho. */
@media (max-width: 720px) {
    body[data-authenticated='true']:has([data-labor-tabs="timeclock"]) .app-modal {
        width: min(var(--app-modal-width, 680px), calc(100vw - 40px)) !important;
    }
}

/* Fichajes en móvil: en los modales con dos botones (p. ej. Cancelar y Registrar fichaje, también con el mapa abierto) los dos
   van en la misma línea, a partes iguales. Con tres o más botones se mantiene la columna de siempre. */
@media (max-width: 720px) {
    body[data-authenticated='true']:has([data-labor-tabs="timeclock"]) .app-modal__footer:not(:has(> :nth-child(3))) {
        display: flex !important;
        flex-direction: row !important;
        flex-wrap: nowrap !important;
        gap: 8px !important;
    }

    body[data-authenticated='true']:has([data-labor-tabs="timeclock"]) .app-modal__footer:not(:has(> :nth-child(3))) .button {
        width: auto !important;
        flex: 1 1 0 !important;
        min-width: 0 !important;
    }
}

/* En móvil no se selecciona texto al tocar o mantener pulsado: en la app se marcaba el texto en vez de usar los botones. Los campos
   donde se escribe y lo que lleve la clase .allow-select siguen permitiendo seleccionar y copiar. */
@media (max-width: 720px) {
    body[data-authenticated='true'] {
        -webkit-user-select: none;
        user-select: none;
        -webkit-touch-callout: none;
        -webkit-tap-highlight-color: transparent;
    }

    body[data-authenticated='true'] input,
    body[data-authenticated='true'] textarea,
    body[data-authenticated='true'] select,
    body[data-authenticated='true'] [contenteditable='true'],
    body[data-authenticated='true'] .allow-select,
    body[data-authenticated='true'] .allow-select * {
        -webkit-user-select: text;
        user-select: text;
    }
}

/* Pantalla de Fichajes (Fichar, Historial, Solicitudes, Ausencias): sin selección de texto en ningún tamaño de pantalla (también en
   PC), para que al pulsar o arrastrar sobre los botones no se marque el texto. Los campos de escritura y .allow-select se
   pueden seguir seleccionando. */
[data-labor-tabs="timeclock"],
[data-labor-tabs="timeclock"] * {
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
}

[data-labor-tabs="timeclock"] input,
[data-labor-tabs="timeclock"] textarea,
[data-labor-tabs="timeclock"] select,
[data-labor-tabs="timeclock"] [contenteditable='true'],
[data-labor-tabs="timeclock"] .allow-select,
[data-labor-tabs="timeclock"] .allow-select * {
    -webkit-user-select: text;
    user-select: text;
}

/* Hora del reloj: cada cifra en una caja de ancho fijo (y los dos puntos en una más estrecha) en los tres diseños, claro y oscuro,
   para que no se mueva al cambiar los números. */
.tc-hud__time { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1, 'lnum' 1; white-space: nowrap; }
.tc-hud__time .tc-d { display: inline-block; width: 0.66em; text-align: center; }
.tc-hud__time .tc-c { display: inline-block; width: 0.32em; text-align: center; }

/* ===== Proyectos (módulo configurable): piezas propias; el resto reutiliza las clases wh-* de Almacén ===== */
.proj-chip { display: inline-flex; align-items: center; gap: 6px; padding: 2px 8px; border-radius: 3px; font-size: .74rem; font-weight: 800; white-space: nowrap; background: color-mix(in srgb, var(--c, #64748b) 14%, var(--surface, #fff)); color: color-mix(in srgb, var(--c, #64748b) 80%, #000); border-left: 3px solid var(--c, #64748b); }
.proj-late { color: var(--danger, #b91c1c); font-weight: 800; }
.proj-multiline { white-space: pre-wrap; overflow-wrap: anywhere; }
.proj-row { cursor: pointer; }
.proj-row:hover td { background: var(--surface-hover, rgba(0, 0, 0, .04)); }
.proj-mine { margin: 0; }
.proj-actions { margin: 0 0 var(--space-3, 10px); }
.proj-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3, 10px); margin-bottom: var(--space-3, 10px); }
.proj-head__title { flex: 1 1 220px; min-width: 0; }
.proj-head__title h3 { margin: 0; font-size: 1.15rem; overflow-wrap: anywhere; }
.proj-head__status .input { min-height: 34px; padding: 4px 10px; font-size: .84rem; width: auto; }
.proj-crumbs { font-size: .76rem; color: var(--text-soft); margin-bottom: 2px; }
.proj-crumb { border: 0; background: none; padding: 0; color: var(--primary-dark, inherit); font: inherit; cursor: pointer; text-decoration: underline; }
.proj-subtabs { margin-bottom: var(--space-3, 10px); }
.proj-count { display: inline-block; min-width: 18px; padding: 0 5px; margin-left: 4px; border-radius: 3px; background: color-mix(in srgb, var(--primary) 16%, var(--surface, #fff)); color: var(--primary-dark); font-size: .7rem; font-weight: 800; text-align: center; }
.proj-facts { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px 16px; margin: 0 0 var(--space-3, 10px); }
.proj-facts > div { min-width: 0; }
.proj-facts dt { font-size: .72rem; font-weight: 700; color: var(--text-soft); text-transform: uppercase; letter-spacing: .03em; }
.proj-facts dd { margin: 2px 0 0; overflow-wrap: anywhere; }
.proj-desc { margin: 0 0 var(--space-3, 10px); padding: 8px 10px; background: var(--surface-soft, rgba(0, 0, 0, .03)); border-radius: 3px; }
.proj-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.proj-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 3px; background: var(--surface, #fff); }
.proj-item--click { cursor: pointer; }
.proj-item--click:hover { background: var(--surface-hover, rgba(0, 0, 0, .04)); }
.proj-item.is-done .proj-item__main strong { text-decoration: line-through; color: var(--text-soft); }
.proj-item__main { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }
.proj-item__main small { color: var(--text-soft); overflow-wrap: anywhere; }
.proj-item__tools { display: flex; gap: 2px; flex: none; }
.proj-check input { width: 20px; height: 20px; cursor: pointer; }
.proj-totals { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 8px; margin-bottom: var(--space-3, 10px); }
.proj-totals > div { padding: 8px 10px; border: 1px solid var(--border); border-radius: 3px; display: grid; gap: 2px; }
.proj-totals span { font-size: .72rem; color: var(--text-soft); text-transform: uppercase; font-weight: 700; }
.proj-totals strong { font-size: 1.05rem; }
.proj-note-new { display: grid; gap: 6px; margin-bottom: var(--space-3, 10px); }
.proj-note-new .button { justify-self: end; }
.proj-day { margin: var(--space-3, 10px) 0 6px; text-transform: capitalize; font-size: .9rem; }
.proj-foot { display: flex; flex-wrap: wrap; gap: 8px; margin-top: var(--space-4, 14px); padding-top: var(--space-3, 10px); border-top: 1px solid var(--border); }
.proj-cfg-block { margin-bottom: var(--space-4, 14px); }
.proj-cfg-block__head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.proj-cfg-block__head h4 { margin: 0; }
.proj-cfg-block__head p { margin: 2px 0 0; }
.proj-inline { display: flex; gap: 8px; max-width: 460px; }
.proj-inline .input { flex: 1 1 auto; }
.proj-lk-results { display: grid; gap: 4px; max-height: 260px; overflow-y: auto; }
.proj-lk-item { text-align: left; padding: 8px 10px; border: 1px solid var(--border); border-radius: 3px; background: var(--surface, #fff); font: inherit; cursor: pointer; }
.proj-lk-item:hover { background: var(--surface-hover, rgba(0, 0, 0, .05)); }
@media (max-width: 720px) {
    .proj-head__status { width: 100%; }
    .proj-head__status .input { width: 100%; }
    .proj-facts { grid-template-columns: 1fr 1fr; }
    .proj-inline { max-width: none; }
}

/* Constructor de campos de Proyectos */
.proj-palette__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; }
.proj-palette__card { display: grid; gap: 3px; text-align: left; padding: 10px 12px; border: 1px solid var(--border); border-radius: 3px; background: var(--surface, #fff); font: inherit; cursor: pointer; }
.proj-palette__card:hover { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 6%, var(--surface, #fff)); }
.proj-palette__card small { color: var(--text-soft); font-size: .74rem; line-height: 1.25; }
.proj-arrow { font-weight: 800; }
.proj-stars { color: #d99a00; letter-spacing: 1px; }
.proj-bar { display: inline-block; width: 90px; height: 8px; border-radius: 3px; background: color-mix(in srgb, var(--primary) 14%, var(--surface, #fff)); overflow: hidden; vertical-align: middle; }
.proj-bar i { display: block; height: 100%; background: var(--primary); }
.proj-swatch { display: inline-block; width: 14px; height: 14px; border-radius: 3px; border: 1px solid var(--border); vertical-align: middle; }
.proj-maplink { margin-left: 6px; white-space: nowrap; }
.proj-geo { margin-top: 6px; }
.proj-tick { display: inline-block; margin-right: 8px; color: var(--text-soft); }
.proj-tick.is-on { color: var(--success, #15803d); font-weight: 700; }
.proj-check-sum { font-weight: 800; margin-right: 6px; }

/* Proyectos — lo que ve el trabajador: compacto y pensado para el móvil (la administración no cambia). */
.proj-worker .proj-cards { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.proj-worker .proj-card { display: grid; gap: 3px; padding: 8px 10px; border: 1px solid var(--border); border-left: 4px solid var(--primary); border-radius: 3px; background: var(--surface, #fff); cursor: pointer; -webkit-tap-highlight-color: transparent; }
.proj-worker .proj-card:active { background: var(--surface-hover, rgba(0, 0, 0, .06)); }
.proj-worker .proj-card.is-closed { opacity: .65; border-left-color: var(--border); }
.proj-worker .proj-card__top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.proj-worker .proj-card__top strong { font-size: .95rem; line-height: 1.2; overflow-wrap: anywhere; }
.proj-worker .proj-card__top .proj-chip { flex: none; }
.proj-worker .proj-card__meta { display: flex; flex-wrap: wrap; gap: 2px 10px; font-size: .74rem; color: var(--text-soft); }
.proj-worker .proj-card__fields { display: flex; flex-wrap: wrap; gap: 2px 10px; font-size: .78rem; }
.proj-worker .proj-card__fields em { font-style: normal; font-size: .68rem; text-transform: uppercase; color: var(--text-soft); font-weight: 700; margin-right: 3px; }
.proj-worker .proj-empty { padding: 14px 4px; text-align: center; }
.proj-worker .proj-back { min-width: 40px; min-height: 40px; padding: 0 12px; }
.proj-worker .proj-code { color: var(--text-soft); font-size: .72rem; }
.proj-worker .proj-when { flex: none; width: 42px; text-align: center; line-height: 1.05; padding: 4px 0; border-radius: 3px; background: color-mix(in srgb, var(--primary) 12%, var(--surface, #fff)); color: var(--primary-dark); }
.proj-worker .proj-when b { display: block; font-size: 1.15rem; }
.proj-worker .proj-when span { font-size: .66rem; text-transform: uppercase; font-weight: 800; }
@media (max-width: 720px) {
    .proj-worker.proj-layout { gap: 8px; }
    .proj-worker > .wh-panel { padding: 8px; }
    .proj-worker .wh-toolbar { gap: 6px; margin-bottom: 6px; }
    .proj-worker .wh-toolbar__filters { flex-wrap: nowrap; gap: 6px; width: 100%; }
    .proj-worker .wh-toolbar__filters input[type='search'] { flex: 1 1 0; min-width: 0; width: auto; }
    .proj-worker .wh-toolbar__filters select { flex: 0 0 auto; max-width: 42%; }
    .proj-worker .wh-toolbar__filters .input { min-height: 38px; }
    .proj-worker .wh-toolbar__actions { width: 100%; }
    .proj-worker .wh-toolbar__actions .button { flex: 1 1 auto; justify-content: center; min-height: 40px; }
    .proj-worker .proj-head { flex-wrap: nowrap; gap: 8px; margin-bottom: 6px; align-items: flex-start; }
    .proj-worker .proj-head__title { flex: 1 1 auto; }
    .proj-worker .proj-head__title h3 { font-size: 1rem; line-height: 1.2; }
    .proj-worker .proj-head__status { width: auto; flex: none; max-width: 44%; }
    .proj-worker .proj-head__status .input { width: 100%; min-height: 38px; font-size: .8rem; }
    .proj-worker .proj-subtabs { overflow-x: auto; flex-wrap: nowrap; margin-bottom: 8px; }
    .proj-worker .proj-subtabs .wh-tabs__btn { padding: 9px 12px; }
    .proj-worker .proj-facts { grid-template-columns: 1fr 1fr; gap: 6px 10px; }
    .proj-worker .proj-facts dt { font-size: .66rem; }
    .proj-worker .proj-facts dd { font-size: .86rem; margin-top: 0; }
    .proj-worker .proj-desc { padding: 6px 8px; font-size: .86rem; }
    .proj-worker .proj-item { padding: 8px; gap: 8px; }
    .proj-worker .proj-check input { width: 26px; height: 26px; }
    .proj-worker .proj-note-new .button { justify-self: stretch; min-height: 40px; }
    .proj-worker .wh-form__section { margin: 8px 0 4px; font-size: .8rem; }
    .proj-worker .proj-foot { margin-top: 8px; padding-top: 8px; }
}

/* Mapas de los campos de ubicación */
.proj-map { height: 190px; margin-top: 6px; border: 1px solid var(--border); border-radius: 3px; overflow: hidden; background: var(--surface-soft, #eef1f5); z-index: 0; }
.proj-map--picker { height: 260px; }
.proj-map.cl-map { height: 380px; }
.proj-map .wh-sub { padding: 10px; margin: 0; }
.proj-facts dd .proj-map { max-width: 520px; }
.proj-facts > div:has(.proj-map) { grid-column: 1 / -1; }
.proj-pin { background: none; border: 0; }
.proj-pin__badge { display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 3px; border: 2px solid #fff; box-shadow: 0 2px 6px rgba(0,0,0,.4); box-sizing: border-box; }
.proj-pin__badge img { filter: brightness(0) invert(1); }
.proj-picker { display: grid; gap: 6px; margin-top: 6px; }
.proj-picker__bar { display: flex; flex-wrap: wrap; gap: 6px; }
@media (max-width: 720px) {
    .proj-map { height: 160px; }
    .proj-map--picker { height: 230px; }
    .proj-map.cl-map { height: 320px; }
}

/* Edición dentro de la propia ficha de Proyectos */
.proj-inline-form { margin-bottom: var(--space-3, 10px); }
.proj-foot--edit { position: sticky; bottom: 0; z-index: 2; background: var(--surface, #fff); }
@media (max-width: 720px) {
    .proj-foot--edit { margin-left: -8px; margin-right: -8px; padding: 8px; }
    .proj-foot--edit .button { flex: 1 1 0; justify-content: center; min-height: 42px; }
}

/* Configuración de Proyectos: flotante, pegada al extremo derecho de la barra de pestañas */
.proj-tabs { display: flex; align-items: center; }
.proj-tabs .proj-tab--config { margin-left: auto; position: sticky; right: 0; }
@media (max-width: 720px) { .proj-tabs .proj-tab--config span { display: none; } }

/* Agenda: calendario mensual */
.proj-cal__bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.proj-cal__nav { display: flex; align-items: center; gap: 6px; }
.proj-cal__title { font-size: 1.05rem; text-transform: capitalize; min-width: 140px; text-align: center; }
.proj-cal__views { display: inline-flex; border: 1px solid var(--border); border-radius: 3px; overflow: hidden; }
.proj-cal__view { border: 0; background: transparent; padding: 6px 14px; font: inherit; font-size: .82rem; font-weight: 700; color: var(--text-soft); cursor: pointer; }
.proj-cal__view.is-active { background: var(--primary); color: #fff; }
.proj-cal { border: 1px solid var(--border); border-radius: 3px; overflow: hidden; background: var(--surface, #fff); }
.proj-cal__head { display: grid; grid-template-columns: repeat(7, 1fr); background: var(--surface-soft, rgba(0, 0, 0, .04)); border-bottom: 1px solid var(--border); }
.proj-cal__head span { padding: 6px 4px; text-align: center; font-size: .72rem; font-weight: 800; color: var(--text-soft); text-transform: uppercase; }
.proj-cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); }
.proj-cal__day { display: flex; flex-direction: column; align-items: stretch; gap: 3px; min-height: 92px; padding: 4px; border: 0; border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); background: var(--surface, #fff); font: inherit; text-align: left; cursor: pointer; min-width: 0; }
.proj-cal__day:nth-child(7n) { border-right: 0; }
.proj-cal__day:hover { background: var(--surface-hover, rgba(0, 0, 0, .04)); }
.proj-cal__day.is-out { background: var(--surface-soft, rgba(0, 0, 0, .03)); color: var(--text-soft); }
.proj-cal__day.is-selected { box-shadow: inset 0 0 0 2px var(--primary); }
.proj-cal__num { font-size: .8rem; font-weight: 800; width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; border-radius: 3px; }
.proj-cal__day.is-today .proj-cal__num { background: var(--primary); color: #fff; }
.proj-cal__chips { display: grid; gap: 2px; min-width: 0; }
.proj-cal__chip { display: block; padding: 1px 5px; border-left: 3px solid var(--c); background: color-mix(in srgb, var(--c) 14%, var(--surface, #fff)); border-radius: 2px; font-size: .68rem; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.proj-cal__chip.is-done { opacity: .5; text-decoration: line-through; }
.proj-cal__more { font-size: .66rem; font-weight: 800; color: var(--text-soft); }
.proj-cal__dots { display: none; gap: 3px; flex-wrap: wrap; }
.proj-cal__dots i { width: 7px; height: 7px; border-radius: 50%; display: block; }
.proj-glyph { flex: none; width: 22px; text-align: center; color: var(--c, var(--primary)); font-size: 1rem; }
.proj-item[style*='--c'] { border-left: 4px solid var(--c); }
@media (max-width: 720px) {
    .proj-cal__day { min-height: 54px; padding: 3px; align-items: center; }
    .proj-cal__chips { display: none; }
    .proj-cal__dots { display: flex; justify-content: center; }
    .proj-cal__title { min-width: 0; font-size: .95rem; }
}

/* Tarjeta flotante de la agenda de Proyectos */
.proj-tip { position: fixed; z-index: 3000; width: 300px; max-width: calc(100vw - 16px); padding: 12px 14px 12px; background: var(--surface, #fff); color: var(--text); border: 1px solid var(--border); border-top: 4px solid var(--c, var(--primary)); border-radius: 3px; box-shadow: 0 12px 32px rgba(0, 0, 0, .22); display: grid; gap: 6px; animation: proj-tip-in .12s ease-out; }
@keyframes proj-tip-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.proj-tip__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.proj-tip__kind { font-size: .7rem; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--c, var(--primary)); }
.proj-tip__done { font-size: .66rem; font-weight: 800; text-transform: uppercase; padding: 1px 6px; border-radius: 3px; background: var(--success-soft, #dcfce7); color: var(--success-soft-ink, #166534); }
.proj-tip__title { font-size: 1rem; line-height: 1.25; overflow-wrap: anywhere; }
.proj-tip__rows { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font-size: .8rem; }
.proj-tip__rows li { display: grid; grid-template-columns: 78px 1fr; gap: 8px; }
.proj-tip__rows b { font-size: .68rem; text-transform: uppercase; color: var(--text-soft); padding-top: 2px; }
.proj-tip__rows span { overflow-wrap: anywhere; }
.proj-tip__rows em { font-style: normal; font-family: monospace; color: var(--text-soft); font-size: .74rem; }
.proj-tip__notes span { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; white-space: pre-wrap; }
.proj-tip__open { justify-self: end; margin-top: 2px; }
.proj-cal__chip[data-tip] { cursor: pointer; }
.proj-cal__chip[data-tip]:hover { filter: brightness(.96); box-shadow: 0 0 0 1px var(--c); }
@media (hover: none) { .proj-tip { display: none; } }

/* Agenda por semanas: lo que dura varios días es una barra continua */
.proj-cal__weeks { display: grid; }
.proj-week { position: relative; border-bottom: 1px solid var(--border); min-height: 96px; }
.proj-week:last-child { border-bottom: 0; }
.proj-week__bg { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(7, 1fr); }
.proj-week__bg .proj-cal__day { min-height: 0; height: 100%; padding: 0; border-bottom: 0; }
.proj-week__fg { position: relative; display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); grid-template-rows: auto repeat(var(--lanes), 22px) auto; pointer-events: none; padding: 3px 0; row-gap: 2px; min-height: 96px; align-content: start; }
.proj-week__fg > * { pointer-events: none; }
.proj-week__fg .proj-cal__num { margin-left: 4px; }
.proj-cal__num.is-out { color: var(--text-soft); }
.proj-cal__cell { display: grid; align-content: start; gap: 2px; padding: 0 3px; min-width: 0; }
.proj-week__fg .proj-cal__chip, .proj-week__fg .proj-bar-ev { pointer-events: auto; }
.proj-bar-ev { display: flex; align-items: center; min-width: 0; margin: 0 3px; padding: 0 8px; background: color-mix(in srgb, var(--c) 78%, var(--surface, #fff)); color: #fff; border-radius: 3px; font-size: .7rem; font-weight: 800; cursor: pointer; overflow: hidden; }
.proj-bar-ev span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.proj-bar-ev:hover { filter: brightness(1.08); box-shadow: 0 0 0 1px var(--c); }
.proj-bar-ev.is-done { opacity: .5; }
.proj-bar-ev.is-cont-left { margin-left: 0; border-top-left-radius: 0; border-bottom-left-radius: 0; }
.proj-bar-ev.is-cont-right { margin-right: 0; border-top-right-radius: 0; border-bottom-right-radius: 0; }
@media (max-width: 720px) {
    .proj-week, .proj-week__fg { min-height: 58px; }
    .proj-week__fg { grid-template-rows: auto repeat(var(--lanes), 8px) auto; }
    .proj-bar-ev { padding: 0; }
    .proj-bar-ev span { display: none; }
    .proj-cal__cell { justify-items: center; }
}

/* Fotos de las personas en Proyectos */
.proj-person-inline { display: inline-flex; align-items: center; gap: 7px; max-width: 100%; margin-right: 8px; vertical-align: middle; }
.proj-person-inline > span:last-child { overflow-wrap: anywhere; }
.proj-chip-person { display: inline-flex; align-items: center; gap: 6px; }
.proj-stack { display: inline-flex; align-items: center; }
.proj-stack__item { margin-left: -7px; border-radius: 50%; box-shadow: 0 0 0 2px var(--surface, #fff); line-height: 0; }
.proj-stack__item:first-child { margin-left: 0; }
.proj-stack__item > span { border-radius: 50% !important; }
.proj-stack__item.is-sup { box-shadow: 0 0 0 2px var(--surface, #fff), 0 0 0 4px #d99a00; }
.proj-stack__more { margin-left: 4px; font-size: .72rem; font-weight: 800; color: var(--text-soft); }
.proj-card__people { margin-left: auto; }
.proj-person-inline > span:first-child, .proj-item > span:first-child[style*='border-radius'] { border-radius: 50% !important; }

/* Pestaña Equipo: tarjetas con foto */
.proj-team { margin-bottom: var(--space-4, 14px); }
.proj-team__title { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; font-size: .9rem; }
.proj-team__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 10px; }
.proj-person { position: relative; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 16px 10px 12px; text-align: center; border: 1px solid var(--border); border-radius: 3px; background: linear-gradient(180deg, color-mix(in srgb, var(--primary) 6%, var(--surface, #fff)), var(--surface, #fff) 60%); transition: transform .12s ease, box-shadow .12s ease; }
.proj-person:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(0, 0, 0, .12); }
.proj-person--sup { border-color: #d99a00; background: linear-gradient(180deg, color-mix(in srgb, #d99a00 12%, var(--surface, #fff)), var(--surface, #fff) 62%); }
.proj-person__photo { position: relative; display: inline-flex; line-height: 0; }
.proj-person__photo > span:first-child { border-radius: 50% !important; box-shadow: 0 0 0 3px var(--surface, #fff), 0 0 0 5px color-mix(in srgb, var(--primary) 35%, transparent); }
.proj-person--sup .proj-person__photo > span:first-child { box-shadow: 0 0 0 3px var(--surface, #fff), 0 0 0 5px #d99a00; }
.proj-person__star { position: absolute; right: -4px; bottom: -2px; width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; background: #d99a00; color: #fff; font-style: normal; font-size: .8rem; box-shadow: 0 0 0 2px var(--surface, #fff); }
.proj-person__name { margin-top: 6px; font-size: .92rem; line-height: 1.2; overflow-wrap: anywhere; }
.proj-person__role { color: var(--text-soft); font-size: .76rem; }
.proj-person__tags { display: flex; flex-wrap: wrap; gap: 4px; justify-content: center; min-height: 4px; }
.proj-person__del { position: absolute; top: 4px; right: 4px; opacity: 0; transition: opacity .12s ease; }
.proj-person:hover .proj-person__del, .proj-person:focus-within .proj-person__del { opacity: 1; }
.proj-person--empty { border-style: dashed; background: transparent; box-shadow: none; transform: none; color: var(--text-soft); }
.proj-person__ghost { display: inline-flex; align-items: center; justify-content: center; width: 56px; height: 56px; border: 2px dashed var(--border); border-radius: 50%; font-size: 1.6rem; color: var(--text-soft); }
.proj-team-owner { display: flex; align-items: center; gap: 10px; margin-bottom: var(--space-3, 10px); padding: 8px 10px; border: 1px solid var(--border); border-radius: 3px; }
.proj-team-owner > span:first-child { font-size: .7rem; font-weight: 800; text-transform: uppercase; color: var(--text-soft); }
@media (hover: none) { .proj-person__del { opacity: 1; } }
@media (max-width: 720px) {
    .proj-team__grid { grid-template-columns: 1fr 1fr; gap: 8px; }
    .proj-person { padding: 12px 6px 10px; }
}

/* ===== Proyectos con el mismo aspecto que Almacén (tokens del skin: colores, radios, sombras) ===== */
.proj-chip { border-left: 0; padding: 2px 8px; font-size: .68rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; background: color-mix(in srgb, var(--c, #64748b) 15%, var(--surface, #fff)); color: color-mix(in srgb, var(--c, #64748b) 82%, #000); }
.proj-head.wh-card { display: flex; align-items: center; margin-bottom: var(--space-4, 14px); padding: var(--space-3, 10px) var(--space-4, 14px); }
.proj-head__title h3 { color: var(--primary-dark); }
.proj-subtabs.wh-subtabs { margin-bottom: var(--space-4, 14px); padding-bottom: var(--space-3, 10px); }
.proj-subtabs .proj-count { margin-left: 2px; background: color-mix(in srgb, currentColor 16%, transparent); color: inherit; }
.wh-card h3 { color: var(--primary-dark); }
.proj-facts dt { color: var(--text-soft); letter-spacing: .08em; font-weight: 800; }
.proj-desc { background: var(--surface-soft); }
.proj-item { background: var(--surface-soft); border-radius: 3px; }
.proj-item--click:hover { background: var(--surface-hover); }
.proj-team__title { color: var(--primary-dark); text-transform: uppercase; letter-spacing: .08em; font-size: .78rem; }
.proj-person { box-shadow: 0 3px 12px color-mix(in srgb, var(--primary) 6%, transparent); }
.proj-worker .proj-card { background: var(--surface); box-shadow: 0 3px 12px color-mix(in srgb, var(--primary) 6%, transparent); }
.proj-cal, .proj-agenda .proj-cal { box-shadow: none; }
.proj-cal__head { background: var(--surface-soft); }
.proj-cal__head span { color: var(--primary-dark); letter-spacing: .08em; }
.proj-cal__title { color: var(--primary-dark); }
.proj-cfg-block__head h3 { margin: 0; display: flex; align-items: center; gap: var(--space-3, 10px); font-size: var(--font-size-md, 1rem); color: var(--primary-dark); }
.proj-cfg-block__head h3 .app-icon { width: 18px; height: 18px; }
.proj-bar-btn { width: 100%; border: 0; background: transparent; padding: 4px 0; font: inherit; color: inherit; text-align: left; cursor: pointer; }
.proj-bar-btn:hover .wh-bar__label { color: var(--primary-dark); text-decoration: underline; }
.proj-tabs { border-bottom: 0; }

/* Supervisores: tarjetas claramente más grandes que las del equipo */
.proj-team > .proj-team__grid:has(.proj-person--sup) { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.proj-person--sup { padding: 24px 16px 18px; gap: 6px; border-width: 2px; box-shadow: 0 8px 22px color-mix(in srgb, #d99a00 22%, transparent); }
.proj-person--sup .proj-person__name { font-size: 1.15rem; margin-top: 10px; }
.proj-person--sup .proj-person__role { font-size: .86rem; }
.proj-person--sup .proj-person__star { width: 32px; height: 32px; font-size: 1.1rem; right: 2px; bottom: 2px; }
.proj-person--member { padding: 12px 8px 10px; }
.proj-person--member .proj-person__name { font-size: .84rem; margin-top: 4px; }
.proj-team__grid:has(.proj-person--member) { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; }
@media (max-width: 720px) {
    .proj-team > .proj-team__grid:has(.proj-person--sup) { grid-template-columns: 1fr; }
    .proj-person--sup .proj-person__photo > span:first-child { width: 96px !important; height: 96px !important; }
    .proj-team__grid:has(.proj-person--member) { grid-template-columns: 1fr 1fr 1fr; }
    .proj-person--member { padding: 10px 4px 8px; }
}

/* Equipo asignado: tarjetas compactas */
.proj-team__grid:has(.proj-person--member) { grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: 6px; }
.proj-person--member { padding: 8px 6px 7px; gap: 2px; }
.proj-person--member .proj-person__photo > span:first-child { box-shadow: 0 0 0 2px var(--surface, #fff), 0 0 0 3px color-mix(in srgb, var(--primary) 35%, transparent); }
.proj-person--member .proj-person__name { font-size: .74rem; margin-top: 3px; line-height: 1.15; }
.proj-person--member .proj-person__role { font-size: .66rem; }
.proj-person--member .proj-person__tags { display: none; }
.proj-person--member .proj-person__del { top: 2px; right: 2px; }
@media (max-width: 720px) {
    .proj-team__grid:has(.proj-person--member) { grid-template-columns: repeat(3, 1fr); gap: 5px; }
    .proj-person--member { padding: 7px 3px 6px; }
}

/* Equipo por niveles: jerarquía centrada; cada nivel más pequeño que el anterior */
.proj-org { display: flex; flex-direction: column; align-items: center; gap: 0; }
.proj-level { position: relative; width: 100%; display: flex; flex-direction: column; align-items: center; padding: 14px 8px 12px; text-align: center; }
.proj-level + .proj-level::before { content: ''; position: absolute; top: -2px; left: 50%; width: 2px; height: 16px; background: color-mix(in srgb, var(--primary) 30%, var(--border)); transform: translateX(-1px); }
.proj-level__title { display: inline-flex; align-items: center; justify-content: center; gap: 8px; margin: 0 0 10px; color: var(--primary-dark); text-transform: uppercase; letter-spacing: .08em; font-size: .74rem; }
.proj-level__num { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 3px; background: var(--primary); color: #fff; font-size: .72rem; letter-spacing: 0; }
.proj-level--l0 .proj-level__num { background: #d99a00; }
.proj-level__row { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; width: 100%; }
.proj-level__empty { color: var(--text-soft); font-size: .76rem; padding: 6px 10px; border: 1px dashed var(--border); border-radius: 3px; }
.proj-org .proj-person { width: var(--pw, 120px); padding: 10px 6px 8px; gap: 2px; align-items: center; text-align: center; transform: none; }
.proj-org .proj-person:hover { transform: translateY(-2px); }
.proj-org .proj-person--l0 { --pw: 150px; border-color: #d99a00; border-width: 2px; box-shadow: 0 6px 16px color-mix(in srgb, #d99a00 22%, transparent); }
.proj-org .proj-person--l1 { --pw: 124px; }
.proj-org .proj-person--l2 { --pw: 108px; }
.proj-org .proj-person--l3 { --pw: 96px; }
.proj-org .proj-person--l4 { --pw: 88px; }
.proj-org .proj-person--l0 .proj-person__name { font-size: .98rem; }
.proj-org .proj-person--l1 .proj-person__name { font-size: .86rem; }
.proj-org .proj-person--l2 .proj-person__name, .proj-org .proj-person--l3 .proj-person__name, .proj-org .proj-person--l4 .proj-person__name { font-size: .76rem; }
.proj-org .proj-person--l3 .proj-person__role, .proj-org .proj-person--l4 .proj-person__role { display: none; }
.proj-org .proj-person__name { margin-top: 4px; line-height: 1.15; }
.proj-org .proj-person__role { font-size: .7rem; }
.proj-org .proj-person__photo > span:first-child { box-shadow: 0 0 0 2px var(--surface, #fff), 0 0 0 4px color-mix(in srgb, var(--primary) 35%, transparent); }
.proj-org .proj-person--l0 .proj-person__photo > span:first-child { box-shadow: 0 0 0 2px var(--surface, #fff), 0 0 0 4px #d99a00; }
.proj-org .proj-person__star { width: 22px; height: 22px; font-size: .8rem; right: -4px; bottom: -2px; }
.proj-team-owner { justify-content: center; }
@media (max-width: 720px) {
    .proj-org .proj-person--l0 { --pw: 132px; }
    .proj-org .proj-person--l1 { --pw: 108px; }
    .proj-org .proj-person--l2 { --pw: 96px; }
    .proj-org .proj-person--l3, .proj-org .proj-person--l4 { --pw: 86px; }
    .proj-level__row { gap: 7px; }
}

/* Constructor (define cómo es el espacio) y editor (rellena los datos de un elemento): se distinguen a primera vista */
.proj-mode-banner { display: flex; align-items: center; gap: 12px; margin-bottom: var(--space-4, 14px); padding: 10px 14px; border-radius: 3px; font-size: .84rem; line-height: 1.35; }
.proj-mode-banner strong { display: block; font-size: .72rem; text-transform: uppercase; letter-spacing: .12em; }
.proj-mode-banner__icon { flex: none; display: grid; place-items: center; width: 38px; height: 38px; border-radius: 3px; }
.proj-mode-banner__icon .app-icon { width: 20px; height: 20px; }
.proj-mode-banner--builder { background: color-mix(in srgb, var(--primary) 9%, var(--surface, #fff)); border: 2px dashed color-mix(in srgb, var(--primary) 55%, transparent); color: var(--primary-dark); }
.proj-mode-banner--builder .proj-mode-banner__icon { background: var(--primary); color: #fff; }
.proj-mode-banner--builder .proj-mode-banner__icon .app-icon { filter: brightness(0) invert(1); }
.proj-mode-banner--builder span:not(.proj-mode-banner__icon) { color: var(--text); }
.proj-mode-banner--editor { background: color-mix(in srgb, #22b27a 11%, var(--surface, #fff)); border: 2px solid #22b27a; color: #0f6a49; }
.proj-mode-banner--editor .proj-mode-banner__icon { background: #22b27a; color: #fff; }
.proj-mode-banner--editor .proj-mode-banner__icon .app-icon { filter: brightness(0) invert(1); }
.proj-mode-banner--editor span:not(.proj-mode-banner__icon) { color: var(--text); }
.proj-builder { background-image: linear-gradient(color-mix(in srgb, var(--primary) 6%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--primary) 6%, transparent) 1px, transparent 1px); background-size: 22px 22px; border-radius: 3px; padding: 2px; }
.proj-builder .wh-card { border-style: dashed; border-color: color-mix(in srgb, var(--primary) 40%, var(--border)); }
.proj-builder .wh-toolbar { align-items: center; }
.proj-building { font-size: .72rem; font-weight: 800; text-transform: uppercase; letter-spacing: .1em; color: var(--primary-dark); }
.proj-editor { padding: 12px; border: 2px solid #22b27a; border-radius: 3px; background: color-mix(in srgb, #22b27a 4%, var(--surface, #fff)); }
.proj-foot--edit { border-top: 2px solid #22b27a; }
.proj-tabs .proj-tab--config { border-style: dashed; }
@media (max-width: 720px) {
    .proj-mode-banner { padding: 8px 10px; gap: 8px; font-size: .78rem; }
    .proj-mode-banner__icon { width: 32px; height: 32px; }
}

/* Altas y ediciones como página (no ventana): la vista de atrás se oculta mientras dura */
[data-pj-content][hidden] { display: none !important; }
.proj-page { display: block; }
.proj-page .proj-page__body { display: grid; gap: var(--space-4, 14px); }
.proj-page .proj-page-form .wh-card { margin-bottom: var(--space-4, 14px); }
.proj-page .proj-foot--edit { margin-top: var(--space-4, 14px); }
.proj-page--editor .proj-foot--edit { border-top-color: #22b27a; }
.proj-page--builder .proj-foot--edit { border-top: 2px dashed color-mix(in srgb, var(--primary) 55%, transparent); }

/* Clientes */
.cl-mark { display: inline-flex; align-items: center; justify-content: center; flex: none; border-radius: 3px; font-weight: 800; color: hsl(var(--h) 55% 28%); background: hsl(var(--h) 70% 90%); border: 1px solid hsl(var(--h) 45% 78%); letter-spacing: .02em; }
.cl-name { display: inline-flex; align-items: center; gap: 10px; min-width: 0; }
.cl-name > span:last-child { min-width: 0; overflow-wrap: anywhere; }
.cl-address { margin: 0 0 6px; overflow-wrap: anywhere; }
.cl-contacts { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 10px; }
.cl-contact { position: relative; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 14px 10px 12px; text-align: center; border: 1px solid var(--border); border-radius: 3px; background: var(--surface, #fff); box-shadow: 0 3px 12px color-mix(in srgb, var(--primary) 6%, transparent); min-width: 0; }
.cl-contact.is-primary { border-color: var(--primary); }
.cl-contact strong { margin-top: 4px; overflow-wrap: anywhere; }
.cl-contact__lines { display: grid; gap: 2px; font-size: .84rem; overflow-wrap: anywhere; }
.cl-contact__tools { position: absolute; top: 4px; right: 4px; display: flex; gap: 2px; }
@media (max-width: 720px) { .cl-contacts { grid-template-columns: 1fr 1fr; } }

/* Desplegables con buscador (cliente, responsable, persona, vehículo) */
.proj-ss { position: relative; }
.proj-ss .input { width: 100%; padding-right: 34px; }
.proj-ss__clear { position: absolute; right: 6px; top: 6px; width: 26px; height: 26px; border: 0; border-radius: 3px; background: transparent; color: var(--text-soft); font-size: 1.2rem; line-height: 1; cursor: pointer; }
.proj-ss__clear:hover { background: var(--surface-hover); color: var(--text); }
.proj-ss__list { position: absolute; z-index: 30; left: 0; right: 0; top: calc(100% + 2px); max-height: 260px; overflow-y: auto; background: var(--surface, #fff); border: 1px solid var(--border); border-radius: 3px; box-shadow: 0 10px 26px rgba(0, 0, 0, .18); }
.proj-ss__item { display: block; width: 100%; padding: 8px 10px; border: 0; border-bottom: 1px solid var(--border); background: transparent; font: inherit; font-size: .88rem; text-align: left; cursor: pointer; color: inherit; }
.proj-ss__item:last-child { border-bottom: 0; }
.proj-ss__item:hover, .proj-ss__item.is-on { background: var(--surface-hover); }
.proj-ss__item.is-on { font-weight: 700; color: var(--primary-dark); }
.proj-ss__empty { padding: 10px; margin: 0; }

/* Materiales de almacén en Proyectos */
.proj-bar.is-over i { background: var(--danger, #dc2626); }
.proj-mat-item { display: grid; gap: 2px; }
.proj-mat-item small { display: block; }

.proj-level__add, .proj-person__move { font: inherit; font-size: .74rem; padding: 2px 4px; border: 1px solid var(--border, #cbd5e1); border-radius: 3px; background: var(--surface, #fff); color: inherit; text-transform: none; letter-spacing: 0; max-width: 150px; }
.proj-level__add { margin-left: 4px; }
.proj-person__move { margin-top: 4px; }

/* Editar / Guardar / Cancelar / Borrar: botones normales a la derecha de la cabecera (sin flotar ni quedarse fijos) */
.proj-dock { display: flex; flex-wrap: wrap; gap: 8px; margin-left: auto; align-items: center; }
.proj-dock .button { white-space: nowrap; }
@media (max-width: 720px) { .proj-dock { width: 100%; } .proj-dock .button { flex: 1 1 0; justify-content: center; } }

/* Digitalizar: documento a la izquierda, datos a la derecha */
.dg-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-4, 14px); align-items: start; }
.dg-view { position: sticky; top: 8px; }
.dg-img { display: block; max-width: 100%; height: auto; margin: 0 auto; border-radius: 3px; }
.dg-frame { width: 100%; height: 78vh; border: 0; border-radius: 3px; background: #fff; }
.dg-drop { border-style: dashed; }
.dg-drop.is-over { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 6%, transparent); }
.dg-queue { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 4px; font-size: .84rem; }
.dg-conf { margin-left: 6px; padding: 1px 5px; border-radius: 3px; font-weight: 700; }
.dg-conf--hi { background: #dcfce7; color: #166534; }
.dg-conf--mid { background: #fef3c7; color: #92400e; }
.dg-conf--lo { background: #fee2e2; color: #991b1b; }
/* Revisión del documento digitalizado (proveedor, proyecto, líneas y entrada en Almacén) */
.dg-intake h3, .dg-intake h4 { margin: 0 0 8px; }
.dg-intake h4 { margin-top: 14px; font-size: .95rem; }
.dg-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px; }
.dg-grid label { display: grid; gap: 4px; font-size: .82rem; font-weight: 700; color: var(--text-soft); align-content: start; }
.dg-grid label .input { font-weight: 400; color: var(--text); width: 100%; }
.dg-span2 { grid-column: 1 / -1; }
.dg-newsup { padding: 10px; border: 1px dashed var(--border); border-radius: 3px; background: var(--surface-soft, transparent); }
.dg-mode { margin: 0; padding: 8px 10px; border: 1px solid var(--border); border-radius: 3px; display: grid; gap: 6px; }
.dg-mode legend { padding: 0 6px; font-size: .8rem; font-weight: 700; color: var(--text-soft); }
.dg-mode label { display: flex; gap: 8px; align-items: flex-start; font-size: .85rem; font-weight: 400; color: var(--text); }
.dg-banner { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 0 0 10px; }
.dg-hint { display: block; margin-top: 2px; }
.dg-lines { margin-top: 6px; }
.dg-lines .wh-table td { vertical-align: top; }
.dg-lines .input { min-width: 0; width: 100%; padding: 4px 6px; font-size: .82rem; }
.dg-c-desc { min-width: 180px; }
.dg-c-ref { min-width: 90px; }
.dg-c-num { min-width: 70px; width: 80px; }
.dg-c-unit { min-width: 56px; width: 64px; }
.dg-c-prod { min-width: 200px; }
.dg-c-lot { min-width: 90px; }
.dg-c-date { min-width: 125px; }
.dg-l-search { margin-top: 4px; }
.dg-l-results { position: relative; z-index: 5; max-height: 200px; overflow-y: auto; border: 1px solid var(--border); border-radius: 3px; background: var(--surface, #fff); }
.dg-lines tr.is-skipped td { opacity: .45; }
.dg-skip { display: inline-flex; gap: 4px; align-items: center; font-size: .76rem; }
.dg-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.dg-actions--left { justify-content: flex-start; margin-top: 8px; padding-top: 0; border-top: 0; }
.dg-undo-products ul { margin: 4px 0 8px 18px; font-size: .84rem; }
.dg-undo-products li.is-blocked { color: var(--text-soft); }
.dg-modal__tabs { display: flex; gap: 4px; margin-bottom: 10px; }
.dg-modal h4 { margin: 14px 0 6px; font-size: .95rem; }
.dg-modal .dg-frame { height: 70vh; }
.dg-tabs { margin-bottom: 12px; }
.dg-company { margin: 10px 0; }
.dg-issue { display: block; font-size: .76rem; padding: 1px 0; }
.dg-issue--error { color: #b91c1c; font-weight: 700; }
.dg-issue--info { color: var(--text-soft); }
a.button.is-disabled { opacity: .5; pointer-events: none; }
.dg-typebox { padding: 12px; margin-bottom: 12px; border: 1px solid var(--border); border-left: 4px solid #d97706; border-radius: 3px; background: var(--surface-soft, transparent); }
.dg-typebox p { margin: 0 0 6px; }
.dg-typebtns { display: flex; flex-wrap: wrap; gap: 8px; }
.dg-filters .wh-toolbar__filters { flex-wrap: wrap; gap: 8px; }
.dg-filters input[type='search'] { min-width: 260px; }
.dg-datef { display: inline-flex; align-items: center; gap: 6px; font-size: .82rem; color: var(--text-soft); }
.dg-totals { margin: 8px 2px; font-size: .88rem; }
.dg-billing { margin-top: 10px; padding: 10px; border: 1px solid var(--border); border-radius: 3px; }
.dg-albs { display: grid; gap: 4px; max-height: 260px; overflow-y: auto; }
.dg-albrow { display: flex; gap: 8px; align-items: flex-start; font-size: .86rem; font-weight: 400; padding: 4px 2px; border-bottom: 1px solid var(--border); }
.dg-tag { margin-left: 6px; padding: 0 5px; border-radius: 3px; font-size: .72rem; font-style: normal; background: var(--surface-hover, #eee); color: var(--text-soft); }
.dg-tag--hot { background: #fef3c7; color: #92400e; font-weight: 700; }
.dg-banner--warn { border-color: #d97706; }
.dg-material { margin-top: 12px; }
.dg-material > summary { cursor: pointer; padding: 6px 0; }
.dg-extracted { margin-top: 14px; }
.dg-extracted > summary { cursor: pointer; padding: 6px 0; }
@media (max-width: 720px) { .dg-grid { grid-template-columns: 1fr; } }
.dg-raw pre { max-height: 260px; overflow: auto; white-space: pre-wrap; font-size: .76rem; }
.dg-split--wide { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); }
@media (max-width: 900px) { .dg-split { grid-template-columns: 1fr; } .dg-view { position: static; } .dg-frame { height: 60vh; } }

/* Constructor: a la derecha del todo, separado del resto de pestañas */
.proj-tabs { width: 100%; flex-wrap: nowrap; }
.proj-tabs .proj-tab--config { margin-left: auto; position: static; flex: none; }
.proj-tabs .proj-tab--config::before { content: ''; position: absolute; left: -16px; top: 20%; bottom: 20%; border-left: 1px solid var(--border); }
.proj-tabs .proj-tab--config { margin-left: auto; padding-left: var(--tab-padding-x); }

/* Pestañas de arriba de Laboral (Dashboard/Trabajadores/Calendario y Personal/Laboral/Config/Turnos…): si las palabras no
   caben, solo iconos (lo decide components/common/utils/compact-tabs.js midiendo la barra; vuelven los textos en cuanto
   hay sitio). El icono de la segunda fila está oculto de normal (.labor-tab-icon { display: none }), aquí se muestra. */
.is-compact-tabs .labor-tab-label,
.is-compact-tabs .logistics-tab-text { display: none !important; }
.is-compact-tabs > * { justify-content: center; }
.is-compact-tabs .labor-tab-icon { display: inline-grid !important; place-items: center; width: auto; height: auto; background: none; font-size: 1.15rem; opacity: 1; }

/* ===== GPS · Trayectos: agenda (calendario del mes, resumen del día y barra de 24 h) ===== */
/* Filtros de Trayectos en una sola línea sobre el mapa (vehículo, calendario, hora inicio/fin) */
.gps-trips-filters.gps-trips-filters--bar {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    align-items: end; gap: 6px; width: 100%; box-sizing: border-box; padding: 6px; margin-bottom: 8px;
}
/* Los campos de la barra van planos: sin el padding/borde de tarjeta de .labor-field, que comía el ancho */
.gps-trips-filters--bar .labor-field { display: flex; flex-direction: column; gap: 2px; margin: 0; min-width: 0; padding: 2px 3px; border: 0; background: transparent; }
.gps-trips-filters--bar .labor-field span { font-size: .68rem; margin: 0; line-height: 1.1; display: block; }
.gps-trips-filters--bar .input,
.gps-trips-filters--bar .button { width: 100%; min-width: 0; height: 34px; min-height: 34px; padding: 0 6px; display: inline-flex; align-items: center; justify-content: center; gap: 4px; box-sizing: border-box; font-size: .8rem; }
.gps-trips-filters--bar select.input { padding-right: 2px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
.gps-trips-filters--bar [data-gps-cal-open] { font-weight: 600; overflow: hidden; }
.gps-trips-filters--bar [data-gps-cal-open] span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; font-size: .8rem; text-transform: none; }
.gps-start-dot { background: none; border: 0; }
.gps-start-dot span { display: block; width: 16px; height: 16px; box-sizing: border-box; border-radius: 50%; background: #16a34a; border: 3px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,.35), 0 1px 3px rgba(0,0,0,.4); }
.gps-finish-flag { background: none; border: 0; }
.gps-csv-buttons { display: flex; gap: 4px; }
.gps-csv-buttons .button { width: 100%; white-space: nowrap; padding-left: 6px; padding-right: 6px; }
.gps-trips-filters--bar [data-gps-cal-open] { white-space: nowrap; font-weight: 600; }
/* Sidebar de la misma altura que el mapa (600px) para que ambos lados queden alineados */
.gps-trips-sidebar { height: 600px; max-height: 600px; box-sizing: border-box; }
@media (max-width: 900px) {
    .gps-trips-sidebar { height: auto; max-height: none; }
}

.gps-agenda { background: var(--surface); border: 1px solid var(--border); border-radius: 3px; padding: 10px; }
.gps-cal__head { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.gps-cal__title { flex: 1; text-align: center; font-size: .86rem; }
.gps-cal__nav, .gps-cal__today { border: 1px solid var(--border); background: var(--surface-soft, var(--surface)); color: var(--text); border-radius: 3px; cursor: pointer; font: inherit; }
.gps-cal__nav { width: 28px; height: 28px; font-size: 1.1rem; line-height: 1; }
.gps-cal__today { padding: 0 10px; height: 28px; font-size: .74rem; font-weight: 700; }
.gps-cal__nav:hover, .gps-cal__today:hover { border-color: var(--primary); color: var(--primary-dark, var(--primary)); }
.gps-cal__grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px; }
.gps-cal__dow { text-align: center; font-size: .64rem; font-weight: 800; letter-spacing: .06em; color: var(--text-soft); padding-bottom: 2px; }
.gps-cal__blank { min-height: 40px; }
.gps-cal__day {
    position: relative; min-height: 40px; padding: 3px 2px; border: 1px solid transparent; border-radius: 3px;
    background: transparent; color: var(--text); cursor: pointer; font: inherit; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
}
.gps-cal__day:hover { border-color: var(--border-strong, var(--border)); }
.gps-cal__n { font-size: .78rem; font-weight: 600; line-height: 1; }
.gps-cal__km { font-size: .56rem; line-height: 1; color: var(--text-soft); }
.gps-cal__day.is-future { opacity: .45; }
.gps-cal__day.has-trips.level-1 { background: color-mix(in srgb, var(--primary) 12%, var(--surface)); }
.gps-cal__day.has-trips.level-2 { background: color-mix(in srgb, var(--primary) 24%, var(--surface)); }
.gps-cal__day.has-trips.level-3 { background: color-mix(in srgb, var(--primary) 40%, var(--surface)); }
.gps-cal__day.has-trips.level-4 { background: color-mix(in srgb, var(--primary) 58%, var(--surface)); }
.gps-cal__day.has-trips .gps-cal__n { font-weight: 800; }
.gps-cal__day.is-today { outline: 2px solid color-mix(in srgb, var(--primary) 70%, transparent); outline-offset: -2px; }
.gps-cal__day.is-selected { background: var(--primary); border-color: var(--primary-dark, var(--primary)); color: #fff; }
.gps-cal__day.is-selected .gps-cal__km { color: rgba(255, 255, 255, .85); }
.gps-cal__foot { margin-top: 8px; font-size: .7rem; color: var(--text-soft); text-align: center; }

.gps-daysummary { background: var(--surface); border: 1px solid var(--border); border-radius: 3px; padding: 10px; }
.gps-daysummary__title { font-weight: 800; font-size: .86rem; text-transform: capitalize; margin-bottom: 8px; }
.gps-daysummary__stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; margin-bottom: 10px; }
.gps-daysummary__stats > div { background: color-mix(in srgb, var(--primary) 8%, var(--surface)); border-radius: 3px; padding: 6px 4px; text-align: center; }
.gps-daysummary__stats strong { display: block; font-size: .9rem; line-height: 1.1; }
.gps-daysummary__stats span { display: block; font-size: .58rem; color: var(--text-soft); text-transform: uppercase; letter-spacing: .04em; margin-top: 2px; }
.gps-timeline__bar { position: relative; height: 18px; background: color-mix(in srgb, var(--text-soft) 12%, var(--surface)); border-radius: 3px; overflow: hidden; }
.gps-timeline__block { position: absolute; top: 2px; bottom: 2px; border: 0; border-radius: 2px; background: var(--primary); opacity: .75; cursor: pointer; padding: 0; min-width: 4px; }
.gps-timeline__block:hover { opacity: 1; }
.gps-timeline__block.is-active { opacity: 1; background: var(--primary-dark, var(--primary)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 35%, transparent); }
.gps-timeline__ticks { display: flex; justify-content: space-between; font-size: .58rem; color: var(--text-soft); margin-top: 2px; }

/* GPS · Trayectos: la columna izquierda se ve entera (sin scroll interno) y el mapa se queda a la vista al bajar. */
.gps-live .gps-trips-sidebar { max-height: none; overflow: visible; }
.gps-live .gps-trips-map-wrap { position: sticky; top: 12px; align-self: start; }
@media (max-width: 900px) {
    .gps-live .gps-trips-map-wrap { position: relative; top: auto; }
}

/* Logística (trabajador): los cuadrados inactivos llevan rayas diagonales flojitas, para que se note que no se pueden usar. */
.logistics-self-tiles .logistics-self-tile:disabled {
    cursor: not-allowed;
    background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0) 0 6px, rgba(255, 255, 255, .30) 6px 9px);
}

/* Logística (trabajador): el cartel «NO ESTÁS USANDO TU VEHÍCULO» tenía display:block (pisaba el inline-flex de la insignia) y el texto
   quedaba pegado arriba: se centra también en vertical. */
.labor-badge.logistics-self-vehicle-warning {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 34px;
    white-space: normal;
}
.labor-badge.logistics-self-vehicle-warning[hidden] { display: none; }

/* Logística (trabajador): el panel de Repostajes tiene el mismo ancho que el resto de paneles (ITV, Seguro, Vestuario...). */
[data-logistics-self-fuel-panel] {
    max-width: 480px;
    margin: 0 auto;
}

.logistics-fuel-card {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px 12px;
    margin-bottom: 8px;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: var(--surface);
    font-size: .86rem;
}
.logistics-fuel-card__top { display: flex; justify-content: space-between; gap: 8px; font-weight: 700; }
.logistics-fuel-card__meta { color: var(--text-soft); font-size: .78rem; }

/* Panel de fichajes: un botón desactivado por administración queda muy difuminado y casi invisible (no se distingue qué es, no molesta
   y no se puede pulsar), pero conserva su hueco para que el diseño no cambie. */
.timeclock-panel-muted {
    opacity: .16;
    filter: blur(2.5px) grayscale(1);
    pointer-events: none;
    user-select: none;
}

/* Laboral → Requisitos y accesos → «Panel de fichajes»: botones-toggle con la forma y la distribución del panel real. Encendido = iluminado;
   apagado = difuminado y de trazo discontinuo (como lo verá el trabajador). */
.tc-pc { display: flex; flex-direction: column; gap: 14px; max-width: 460px; margin: 0 auto; padding: 14px 12px; border: 1px solid var(--border); border-radius: 3px; background: color-mix(in srgb, var(--primary) 4%, var(--surface)); }
.tc-pc__note { margin: 0 0 10px; font-size: .72rem; text-align: center; }
.tc-pc-row { display: grid; gap: 10px; align-items: stretch; }
.tc-pc-row--kinds { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; }
.tc-pc-row--punch { grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr) minmax(0, 1fr); align-items: center; }
.tc-pc-row--two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tc-pc-row--breaks { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.tc-pc-tile {
    position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
    min-width: 0; min-height: 58px; padding: 8px 6px; margin: 0; text-align: center; cursor: pointer; user-select: none;
    border: 1px solid color-mix(in srgb, var(--primary) 55%, var(--border)); border-radius: 3px;
    background: color-mix(in srgb, var(--primary) 14%, var(--surface)); color: var(--text);
    transition: opacity .15s, filter .15s, background .15s, border-color .15s;
}
.tc-pc-tile input { position: absolute; opacity: 0; pointer-events: none; width: 1px; height: 1px; }
.tc-pc-tile__icon { font-size: 1.15rem; line-height: 1; }
.tc-pc-tile__label { font-size: .68rem; font-weight: 700; line-height: 1.1; overflow-wrap: anywhere; }
.tc-pc-tile:hover:not(:has(input:disabled)) { border-color: var(--primary); }
.tc-pc-tile:has(input:disabled) { cursor: not-allowed; }
/* apagado */
.tc-pc-tile:not(:has(input:checked)):not(.tc-pc-tile--punch) {
    border-style: dashed; border-color: var(--border-strong, var(--border)); background: transparent; opacity: .42; filter: blur(.6px) grayscale(1);
}
/* selector de tipo: segmentado, sin huecos entre botones */
.tc-pc-row--kinds .tc-pc-tile { flex-direction: row; gap: 6px; min-height: 40px; border-radius: 0; }
.tc-pc-row--kinds .tc-pc-tile:first-child { border-radius: 3px 0 0 3px; }
.tc-pc-row--kinds .tc-pc-tile:last-child { border-radius: 0 3px 3px 0; }
.tc-pc-row--kinds .tc-pc-tile + .tc-pc-tile { margin-left: -1px; }
.tc-pc-row--kinds .tc-pc-tile__icon { font-size: .95rem; }
/* botones de los lados del de fichar: más pequeños que el central */
.tc-pc-tile--side { min-height: 52px; }
/* el botón de fichar, fijo: grande y destacado */
.tc-pc-tile--punch {
    min-height: 92px; cursor: default; gap: 6px; border: 2px solid var(--primary); background: color-mix(in srgb, var(--primary) 22%, var(--surface)); box-shadow: 0 4px 12px color-mix(in srgb, var(--primary) 25%, transparent);
}
.tc-pc-tile--punch .tc-pc-tile__icon { font-size: 1.7rem; }
.tc-pc-tile--punch .tc-pc-tile__label { font-size: .8rem; }
.tc-pc-tile__lock { position: absolute; top: 4px; right: 5px; font-size: .62rem; opacity: .65; }
@media (max-width: 380px) {
    .tc-pc { padding: 10px 8px; }
    .tc-pc-tile__label { font-size: .62rem; }
}

/* Panel de fichajes en dos columnas: permisos de teletrabajo a la izquierda, la maqueta del panel a la derecha (en pantallas estrechas, una encima de otra). */
.tc-pc-layout { display: flex; flex-wrap: wrap; gap: 18px; align-items: flex-start; }
.tc-pc-side { flex: 1 1 200px; max-width: 260px; display: flex; flex-direction: column; gap: 6px; padding-top: 4px; }
.tc-pc-side__title { margin: 0 0 4px; font-size: .74rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--text-soft); }
.tc-pc-side .labor-toggle { font-size: .8rem; }
.tc-pc-main { flex: 2 1 340px; min-width: 0; }
.tc-pc-main .tc-pc { margin: 0; }

/* Tres columnas: requisitos | maqueta del panel | permisos de teletrabajo. En pantallas estrechas se apilan (requisitos, panel, teletrabajo). */
.tc-pc-layout { gap: 16px; }
.tc-pc-side { flex: 1 1 170px; max-width: 230px; }
.tc-pc-main { flex: 2 1 330px; }
.tc-pc-side--req .labor-toggle, .tc-pc-side--tele .labor-toggle { font-size: .78rem; }

/* La maqueta del panel respeta el atributo hidden (las casillas tienen display:flex propio). */
.tc-pc-tile[hidden], .tc-pc-row[hidden] { display: none; }

/* Panel de fichajes (config): un interruptor marcado pero BLOQUEADO por otro «jefe» apagado se ve en verde claro, para que se note que está
   marcado y que hay otro interruptor que lo bloquea. */
.tc-pc-tile[data-blocked]:has(input:checked) {
    border-style: solid; border-color: #86d3a0; background: color-mix(in srgb, #4ade80 20%, var(--surface)); opacity: .9; filter: none;
}
.labor-toggle[data-blocked]:has(input:checked) .labor-toggle__track { background: #a7e3bd; border-color: #86d3a0; }
.labor-toggle[data-blocked]:has(input:checked) .labor-toggle__label { opacity: .85; }

/* Laboral: Editar / Guardar / Cancelar en un cuadro ARRIBA del menú lateral (que ya es sticky): no se pierden al hacer scroll. */
.labor-subtabs__actions {
    display: flex; flex-direction: row; flex-wrap: wrap; gap: 6px; padding: 0 0 10px; margin: 0 0 4px;
    border-bottom: 1px solid var(--border);
}
/* uno al lado del otro: «Editar» ocupa todo el ancho; «Guardar» y «Cancelar» se reparten la fila */
.labor-subtabs__actions .button { flex: 1 1 0; min-width: 0; justify-content: center; margin: 0; padding-left: 6px; padding-right: 6px; white-space: nowrap; }
.labor-subtabs__actions [hidden] { display: none !important; }
@media (max-width: 900px) {
    /* en pantallas estrechas el menú pasa a ser horizontal: el cuadro va en fila al principio */
    .labor-subtabs__actions { flex-direction: row; flex: 0 0 auto; padding: 0 8px 0 0; margin: 0 4px 0 0; border-bottom: 0; border-right: 1px solid var(--border); }
    .labor-subtabs__actions .button { width: auto; white-space: nowrap; }
}

/* Laboral: el menú lateral (sticky) se pegaba a 8px del borde de arriba y quedaba DEBAJO de la barra superior fija, escondiendo el cuadro de
   Editar/Guardar/Cancelar. Ahora se pega justo debajo de la barra. (Solo en escritorio: en pantallas estrechas el menú es horizontal y no es sticky.) */
@media (min-width: 901px) {
    .labor-subtabs .labor-subtabs__nav { top: calc(var(--topbar-height, 58px) + 8px); }
}
.labor-subtabs__actions { border-bottom-color: var(--border-strong, var(--border)); padding-bottom: 12px; margin-bottom: 6px; }

/* Fichajes (trabajador): las cuatro pestañas (Fichajes, Historial, Solicitudes y Ausencias) y su barra de pestañas tienen el MISMO ancho, como en
   Logística: así se simula en el ordenador cómo se ve en el móvil. */
.labor-tabs[data-labor-tabs="timeclock"] {
    max-width: 480px;
    margin-left: auto;
    margin-right: auto;
}

/* Fichajes (trabajador): el botón de mensajes del día (la «i») y las bolas que salen al marcar días en Ausencias (contador, goma y enviar) viven en UN
   solo contenedor flotante a la derecha, en columna y con el mismo aspecto: así ya no se pisan unos a otros. */
.timeclock-fab-stack {
    position: fixed; top: 50%; right: 14px; transform: translateY(-50%); z-index: 45;
    display: flex; flex-direction: column; align-items: center; gap: 10px; pointer-events: none;
}
.timeclock-fab-stack > * { pointer-events: auto; }
.timeclock-fab-stack > .timeclock-messages-info,
.timeclock-fab-stack > .labor-leave-selection-bubble,
.timeclock-fab-stack > .labor-leave-clear-bubble,
.timeclock-fab-stack > .labor-leave-send-bubble {
    position: relative !important; top: auto !important; right: auto !important; transform: none !important; margin: 0 !important;
    flex: none; width: 44px !important; height: 44px !important; border-radius: 50% !important; z-index: auto !important;
    box-shadow: 0 4px 12px rgba(15, 23, 42, 0.24);
}
.timeclock-fab-stack > .timeclock-messages-info { background: #fbbf24; display: inline-flex; align-items: center; justify-content: center; }
.timeclock-fab-stack .timeclock-messages-info__dot { font-size: 1.15rem; }
.timeclock-fab-stack > [hidden] { display: none !important; }
@media (max-width: 900px) {
    .timeclock-fab-stack { right: 8px; gap: 8px; }
    .timeclock-fab-stack > .timeclock-messages-info,
    .timeclock-fab-stack > .labor-leave-selection-bubble,
    .timeclock-fab-stack > .labor-leave-clear-bubble,
    .timeclock-fab-stack > .labor-leave-send-bubble { width: 40px !important; height: 40px !important; }
}

/* Fichajes: firma de la jornada («Firmas pendientes» y el cuadro de firma) */
.timeclock-signatures { margin: 14px auto 0; max-width: 420px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 3px; background: color-mix(in srgb, var(--primary) 6%, var(--surface)); }
.timeclock-signatures__title { margin: 0 0 8px; font-size: .78rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--text-soft); }
.timeclock-signatures__row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 7px 0; border-top: 1px solid var(--border); }
.timeclock-signatures__row:first-child { border-top: 0; }
.timeclock-signatures__info { display: flex; flex-direction: column; min-width: 0; font-size: .84rem; text-transform: capitalize; }
.timeclock-signatures__info small { color: var(--text-soft); font-size: .7rem; text-transform: none; }
.timeclock-sign__date { margin: 0 0 6px; font-weight: 800; text-transform: capitalize; }
.timeclock-sign__list { list-style: none; margin: 0 0 8px; padding: 0; border: 1px solid var(--border); border-radius: 3px; }
.timeclock-sign__list li { display: flex; justify-content: space-between; padding: 5px 9px; font-size: .84rem; border-top: 1px solid var(--border); }
.timeclock-sign__list li:first-child { border-top: 0; }
.timeclock-sign__total { margin: 0 0 10px; font-size: .86rem; }

/* Ojo para ver la contraseña (assets/js/password-eye.js) */
.pw-ojo { position: relative; display: block; width: 100%; }
.pw-ojo > .input, .pw-ojo > input { width: 100%; padding-right: 40px; box-sizing: border-box; }
.pw-ojo__boton { position: absolute; top: 50%; right: 6px; transform: translateY(-50%); width: 30px; height: 30px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border: 0; background: transparent; color: inherit; opacity: .6; cursor: pointer; border-radius: 3px; }
.pw-ojo__boton:hover, .pw-ojo__boton:focus-visible { opacity: 1; }
.pw-ojo__boton svg { width: 20px; height: 20px; }
