/* ============================================================================
   Plataforma Integral de Gestión Empresarial · Grupo Vascolor
   Sistema de diseño CSS y diseño responsivo.
   ----------------------------------------------------------------------------
   Orden de lectura:
     1. Tokens          — variables CSS (única fuente de verdad del diseño)
     2. Reset y base    — normalización + tipografía
     3. Estructura      — shell, sidebar, topbar, grid de contenido
     4. Componentes     — KPI, tarjetas, tablas, badges, listas, barras
     5. Utilidades      — helpers puntuales
     6. Responsive      — adaptabilidad móvil
   ========================================================================== */

/* ============================================================================
   1. TOKENS
   ========================================================================== */

:root {
    /* --- Marca -------------------------------------------------------------
       El azul es el color de acción del mockup: nav activo, botón "Nueva obra",
       enlaces y códigos de obra. No se usa para nada decorativo. */
    --color-marca:            #2563EB;
    --color-marca-oscuro:     #1D4ED8;
    --color-marca-claro:      #DBEAFE;
    --color-marca-texto:      #1E40AF;

    /* --- Rail de navegación (azul marino casi negro del mockup) ---------- */
    --color-rail:             #0B1220;
    --color-rail-elevado:     #131C2E;
    --color-rail-texto:       #94A3B8;
    --color-rail-texto-activo:#FFFFFF;

    /* --- Superficies ----------------------------------------------------- */
    --color-lienzo:           #F1F5F9;  /* fondo exterior de la app */
    --color-superficie:       #FFFFFF;  /* tarjetas */
    --color-superficie-suave: #F8FAFC;  /* cabeceras de tabla, hover */
    --color-borde:            #E5E7EB;
    --color-borde-suave:      #F1F5F9;

    /* --- Texto ----------------------------------------------------------- */
    --color-texto:            #0F172A;
    --color-texto-medio:      #475569;
    --color-texto-tenue:      #94A3B8;

    /* --- Acentos semánticos ----------------------------------------------
       Cada hue del mockup significa algo concreto; no son adorno:
         azul    → actividad/obras       verde   → dinero entrante/OK
         violeta → personas              ámbar   → pendiente de acción
         rojo    → vencido/urgente       cian    → rendimiento/medición       */
    --color-azul:             #3B82F6;
    --color-verde:            #22C55E;
    --color-violeta:          #8B5CF6;
    --color-ambar:            #F59E0B;
    --color-rojo:             #EF4444;
    --color-cian:             #06B6D4;

    /* Fondos suaves para iconos y badges (mismo hue, 12% aprox.) */
    --bg-azul:                #EFF6FF;
    --bg-verde:               #ECFDF5;
    --bg-violeta:             #F5F3FF;
    --bg-ambar:               #FFFBEB;
    --bg-rojo:                #FEF2F2;
    --bg-cian:                #ECFEFF;
    --bg-neutro:              #F1F5F9;

    /* Tintas de TEXTO de cada acento: variantes oscurecidas de los 6 colores
       de arriba, para cuando el acento tiene que llevarlo un texto (no un
       icono ni un fondo). Los --color-* crudos son de identidad/gráfico —
       verificados con el validador de paletas de la skill dataviz para
       distinción CVD, pero SOLO pasan ~2.2:1 de contraste sobre superficie
       blanca, muy por debajo del 4.5:1 que exige texto pequeño en WCAG AA.
       Regla: el texto lleva tinta de texto, nunca el color de la serie. */
    --texto-azul:             var(--color-marca-texto);
    --texto-verde:            #065F46;
    --texto-violeta:          #5B21B6;
    --texto-ambar:            #92400E;
    --texto-rojo:             #991B1B;
    --texto-cian:             #0E7490;

    /* --- Tipografía -------------------------------------------------------
       Inter es la fuente del mockup. Se sirve local (assets/fonts) para no
       depender de Google Fonts: es requisito RGPD y evita FOUT. */
    --fuente-base: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
                   Roboto, "Helvetica Neue", Arial, sans-serif;
    --fuente-datos: "Inter", ui-monospace, "SF Mono", monospace;

    --texto-2xs:   0.6875rem;  /* 11px · etiquetas de eje, días de semana */
    --texto-xs:    0.75rem;    /* 12px · metadatos, "Hace 15 min" */
    --texto-sm:    0.8125rem;  /* 13px · celdas de tabla, nav */
    --texto-base:  0.875rem;   /* 14px · cuerpo */
    --texto-md:    1rem;       /* 16px · títulos de tarjeta */
    --texto-lg:    1.375rem;   /* 22px · título de página */
    --texto-xl:    1.75rem;    /* 28px · cifras KPI */

    --peso-normal:   400;
    --peso-medio:    500;
    --peso-semi:     600;
    --peso-bold:     700;

    /* --- Espaciado (escala de 4px) --------------------------------------- */
    --esp-1:  0.25rem;
    --esp-2:  0.5rem;
    --esp-3:  0.75rem;
    --esp-4:  1rem;
    --esp-5:  1.25rem;
    --esp-6:  1.5rem;
    --esp-8:  2rem;
    --esp-10: 2.5rem;

    /* --- Formas ---------------------------------------------------------- */
    --radio-sm:   6px;
    --radio-md:   8px;
    --radio-lg:   12px;   /* tarjetas */
    --radio-xl:   16px;   /* shell de la app */
    --radio-full: 999px;

    /* --- Sombras (muy sutiles: el mockup usa borde, no elevación) -------- */
    --sombra-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
    --sombra-md: 0 1px 3px rgba(15, 23, 42, 0.06), 0 1px 2px rgba(15, 23, 42, 0.04);
    --sombra-lg: 0 10px 25px rgba(15, 23, 42, 0.08);
    --sombra-hover: 0 12px 28px -8px rgba(37, 99, 235, 0.16), 0 4px 10px rgba(15, 23, 42, 0.06);

    /* --- Estructura ------------------------------------------------------ */
    --ancho-rail:        232px;
    --alto-topbar:       68px;
    --transicion:        150ms ease;
}

/* ============================================================================
   2. RESET Y BASE
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

* { margin: 0; padding: 0; }

html { -webkit-text-size-adjust: 100%; }

body {
    font-family: var(--fuente-base);
    font-size: var(--texto-base);
    line-height: 1.5;
    color: var(--color-texto);
    background-color: var(--color-lienzo);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

img, svg { display: block; max-width: 100%; }

/* Tamaño estándar para iconos SVG inline generados por Icono::render().
   Sin width/height explícitos, el reset max-width:100% los expande al 100% del
   contenedor padre. Todas las clases de icono deben enumerarse aquí. */
svg.icono           { width: 20px; height: 20px; flex-shrink: 0; }
svg.icono--sm       { width: 16px; height: 16px; flex-shrink: 0; }
svg.icono--lg       { width: 24px; height: 24px; flex-shrink: 0; }
svg.campana__icono  { width: 22px; height: 22px; flex-shrink: 0; }
svg.boton__icono    { width: 18px; height: 18px; flex-shrink: 0; }
svg.movil-tab__icono { width: 20px; height: 20px; flex-shrink: 0; }
svg.alerta__icono   { width: 20px; height: 20px; flex-shrink: 0; }
svg.vacio__icono    { width: 32px; height: 32px; flex-shrink: 0; }
svg.kpi__icono      { width: 24px; height: 24px; flex-shrink: 0; }
svg.evento__icono   { width: 18px; height: 18px; flex-shrink: 0; }

button, input, select, textarea { font: inherit; color: inherit; }

button { background: none; border: none; cursor: pointer; }

a { color: var(--color-marca); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Foco visible y consistente: requisito de accesibilidad, nunca `outline:none`
   sin sustituto. */
:focus-visible {
    outline: 2px solid var(--color-marca);
    outline-offset: 2px;
    border-radius: var(--radio-sm);
}

/* Respeta la preferencia del sistema de reducir movimiento. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

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

/* Salto al contenido: primer tabulable de la página. */
.saltar-al-contenido {
    position: absolute;
    top: var(--esp-2);
    left: var(--esp-2);
    z-index: 100;
    padding: var(--esp-2) var(--esp-4);
    background: var(--color-marca);
    color: #FFF;
    border-radius: var(--radio-md);
    transform: translateY(-200%);
    transition: transform var(--transicion);
}
.saltar-al-contenido:focus { transform: translateY(0); }

/* ============================================================================
   3. ESTRUCTURA
   ========================================================================== */

/* Mobile-first: una sola columna. El rail se convierte en cajón deslizante. */
.shell {
    min-height: 100vh;
    background: var(--color-superficie);
}

/* --- Rail de navegación --------------------------------------------------- */

.rail {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 40;
    display: flex;
    flex-direction: column;
    width: var(--ancho-rail);
    background:
        radial-gradient(120% 60% at 50% 0%, rgba(59, 130, 246, 0.10), transparent 60%),
        var(--color-rail);
    transform: translateX(-100%);
    transition: transform var(--transicion);
}
.rail[data-abierto="true"] { transform: translateX(0); }

.rail__marca {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    height: var(--alto-topbar);
    padding: 0 var(--esp-5);
    flex-shrink: 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.rail__marca-logo {
    width: 32px;
    height: 32px;
    max-width: 32px;
    max-height: 32px;
    border-radius: var(--radio-md);
    background: #ffffff;
    display: grid;
    place-items: center;
    flex-shrink: 0;
    padding: 3px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(255, 255, 255, 0.08);
}
.rail__marca-logo img {
    width: 24px !important;
    height: 24px !important;
    max-width: 24px !important;
    max-height: 24px !important;
    object-fit: contain;
    display: block;
}

.rail__nombre {
    font-size: var(--texto-2xs);
    font-weight: var(--peso-medio);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-rail-texto);
    line-height: 1.3;
}
.rail__nombre strong {
    display: block;
    font-size: var(--texto-base);
    font-weight: var(--peso-bold);
    letter-spacing: 0.02em;
    color: var(--color-rail-texto-activo);
}

.rail__nav {
    flex: 1;
    overflow-y: auto;
    padding: var(--esp-4) var(--esp-3);
    scrollbar-width: thin;
    scrollbar-color: var(--color-rail-elevado) transparent;
}
.rail__nav::-webkit-scrollbar { width: 6px; }
.rail__nav::-webkit-scrollbar-thumb { background: var(--color-rail-elevado); border-radius: var(--radio-full); }
.rail__nav::-webkit-scrollbar-track { background: transparent; }

.rail__lista { list-style: none; display: grid; gap: 2px; }

.rail__enlace {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    padding: var(--esp-3) var(--esp-3);
    border-radius: var(--radio-md);
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    color: var(--color-rail-texto);
    transition: background var(--transicion), color var(--transicion), transform var(--transicion);
}
.rail__enlace:hover {
    background: var(--color-rail-elevado);
    color: var(--color-rail-texto-activo);
    text-decoration: none;
    transform: translateX(2px);
}

/* Estado activo: `aria-current="page"` es el selector — el estado visual y
   el semántico no pueden divergir. */
.rail__enlace[aria-current="page"] {
    position: relative;
    background: linear-gradient(90deg, rgba(37, 99, 235, 0.18), var(--color-rail-elevado) 70%);
    color: var(--color-rail-texto-activo);
    font-weight: var(--peso-semi);
    box-shadow: inset 0 0 0 1px rgba(59, 130, 246, 0.16);
}
.rail__enlace[aria-current="page"]::before {
    content: "";
    position: absolute;
    left: calc(var(--esp-3) * -1);
    top: 50%;
    transform: translateY(-50%);
    width: 3px; height: 22px;
    background: var(--color-marca);
    border-radius: 0 var(--radio-sm) var(--radio-sm) 0;
    box-shadow: 0 0 8px rgba(37, 99, 235, 0.6);
}

.rail__icono { width: 18px; height: 18px; flex-shrink: 0; }

/* Ficha de usuario al pie del rail. */
.rail__usuario {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    margin: var(--esp-3);
    padding: var(--esp-3);
    background: var(--color-rail-elevado);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: var(--radio-lg);
    flex-shrink: 0;
    transition: background var(--transicion), border-color var(--transicion);
}
.rail__usuario:hover {
    background: #1B2740;
    border-color: rgba(255, 255, 255, 0.12);
    text-decoration: none;
}
.rail__usuario-nombre {
    font-size: var(--texto-sm);
    font-weight: var(--peso-semi);
    color: var(--color-rail-texto-activo);
}
.rail__usuario-rol {
    font-size: var(--texto-xs);
    color: var(--color-rail-texto);
}

/* Velo que cubre el contenido con el cajón abierto (solo móvil). */
.rail-velo {
    position: fixed;
    inset: 0;
    z-index: 30;
    background: rgba(15, 23, 42, 0.5);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--transicion), visibility var(--transicion);
}
.rail-velo[data-visible="true"] { opacity: 1; visibility: visible; }

/* --- Barra superior ------------------------------------------------------- */

.topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: var(--esp-4);
    height: var(--alto-topbar);
    padding: 0 var(--esp-4);
    background: var(--color-superficie);
    border-bottom: 1px solid var(--color-borde);
    box-shadow: 0 4px 16px -12px rgba(15, 23, 42, 0.16);
}

.topbar__hamburguesa {
    display: grid;
    place-items: center;
    width: 38px; height: 38px;
    border-radius: var(--radio-md);
    color: var(--color-texto-medio);
    transition: background var(--transicion);
}
.topbar__hamburguesa:hover { background: var(--color-superficie-suave); }
.topbar__hamburguesa-icono { width: 18px; height: 18px; }

.buscador {
    position: relative;
    flex: 1;
    max-width: 560px;
}
.buscador__icono {
    position: absolute;
    left: var(--esp-4);
    top: 50%;
    transform: translateY(-50%);
    width: 16px; height: 16px;
    color: var(--color-texto-tenue);
    pointer-events: none;
    transition: color var(--transicion);
}
.buscador:focus-within .buscador__icono { color: var(--color-marca); }
.buscador__campo {
    width: 100%;
    height: 42px;
    padding: 0 var(--esp-4) 0 var(--esp-10);
    background: var(--color-superficie-suave);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-full);
    font-size: var(--texto-sm);
    transition: border-color var(--transicion), background var(--transicion), box-shadow var(--transicion);
}
.buscador__campo::placeholder { color: var(--color-texto-tenue); }
.buscador__campo:focus {
    background: var(--color-superficie);
    border-color: var(--color-marca);
    outline: none;
    box-shadow: 0 0 0 3px var(--color-marca-claro);
}
.buscador__atajo {
    position: absolute;
    right: var(--esp-3);
    top: 50%;
    transform: translateY(-50%);
    padding: 2px var(--esp-2);
    background: var(--color-superficie);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-sm);
    font-size: var(--texto-2xs);
    color: var(--color-texto-tenue);
}

.topbar__acciones {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    margin-left: auto;
}

.campana {
    position: relative;
    display: grid;
    place-items: center;
    width: 38px; height: 38px;
    border-radius: var(--radio-md);
    color: var(--color-texto-medio);
    transition: background var(--transicion), color var(--transicion);
}
.campana:hover { background: var(--color-superficie-suave); color: var(--color-texto); }
.topbar__hamburguesa:active, .campana:active { transform: scale(0.94); }
/* Sin esto, el <svg> del icono (solo tiene viewBox, sin width/height propios)
   cae al tamaño de reemplazo por defecto del navegador -- mucho más grande
   que los 38px del botón que lo contiene -- y se ve gigante y deformado. */
.campana__icono { width: 18px; height: 18px; }
.campana__contador {
    position: absolute;
    top: 4px; right: 4px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    display: grid;
    place-items: center;
    background: var(--color-marca);
    color: #FFF;
    border: 2px solid var(--color-superficie);
    border-radius: var(--radio-full);
    font-size: 10px;
    font-weight: var(--peso-bold);
    line-height: 1;
}
.campana__contador::after {
    content: "";
    position: absolute;
    inset: -4px;
    border-radius: inherit;
    border: 2px solid var(--color-marca);
    animation: campana-pulso 1.4s ease-out 3;
}
@keyframes campana-pulso {
    from { transform: scale(0.7); opacity: 0.6; }
    to   { transform: scale(1.7); opacity: 0; }
}

.usuario-menu {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    padding: var(--esp-2);
    border-radius: var(--radio-md);
    transition: background var(--transicion);
}
.usuario-menu:hover { background: var(--color-superficie-suave); }
.usuario-menu:hover .avatar { box-shadow: 0 0 0 2px var(--color-marca-claro); }
.usuario-menu .avatar { transition: box-shadow var(--transicion); }
.usuario-menu__datos { display: none; text-align: left; }
.usuario-menu__nombre {
    font-size: var(--texto-sm);
    font-weight: var(--peso-semi);
    line-height: 1.3;
}
.usuario-menu__rol {
    font-size: var(--texto-xs);
    color: var(--color-texto-tenue);
    line-height: 1.3;
}

/* --- Menú Desplegable de Usuario --- */
.usuario-menu-dropdown {
    position: absolute;
    right: 0;
    top: 100%;
    margin-top: var(--esp-2);
    background: var(--color-superficie);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-lg);
    box-shadow: var(--sombra-lg);
    padding: var(--esp-1) 0;
    z-index: 50;
    min-width: 160px;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px) scale(0.98);
    transition: opacity var(--transicion), transform var(--transicion), visibility var(--transicion);
}
.usuario-menu[aria-expanded="true"] + .usuario-menu-dropdown {
    opacity: 1;
    visibility: visible;
    transform: translateY(0) scale(1);
}
.usuario-menu-dropdown a,
.usuario-menu-dropdown button {
    display: block;
    width: 100%;
    padding: var(--esp-2) var(--esp-4);
    text-align: left;
    font-size: var(--texto-sm);
    color: var(--color-texto);
    background: none;
    border: none;
    cursor: pointer;
    transition: background var(--transicion), color var(--transicion);
}
.usuario-menu-dropdown a:hover,
.usuario-menu-dropdown button:hover {
    background: var(--color-superficie-suave);
    text-decoration: none;
}

/* --- Contenido ------------------------------------------------------------ */

.contenido { padding: var(--esp-5) var(--esp-4) var(--esp-10); }

.pagina-cabecera {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--esp-4);
    margin-bottom: var(--esp-5);
}
.pagina-cabecera__texto { flex: 1; min-width: 220px; }
.pagina-titulo {
    font-size: var(--texto-lg);
    font-weight: var(--peso-bold);
    letter-spacing: -0.02em;
}
.pagina-subtitulo {
    font-size: var(--texto-base);
    color: var(--color-texto-tenue);
    margin-top: 2px;
}
.pagina-cabecera__acciones {
    display: flex;
    flex-wrap: wrap;
    gap: var(--esp-3);
}

/* ============================================================================
   4. COMPONENTES
   ========================================================================== */

/* --- Avatar --------------------------------------------------------------- */

.avatar {
    display: grid;
    place-items: center;
    width: 34px; height: 34px;
    border-radius: var(--radio-full);
    background: var(--color-marca-claro);
    color: var(--color-marca-texto);
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    object-fit: cover;
    flex-shrink: 0;
    overflow: hidden;
}
.avatar--sm { width: 26px; height: 26px; font-size: 10px; }
.avatar--lg { width: 40px; height: 40px; font-size: var(--texto-sm); }

/* --- Botones -------------------------------------------------------------- */

.boton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--esp-2);
    height: 40px;
    padding: 0 var(--esp-4);
    border-radius: var(--radio-md);
    font-size: var(--texto-sm);
    font-weight: var(--peso-semi);
    white-space: nowrap;
    transition: background var(--transicion), border-color var(--transicion);
}
.boton:hover { text-decoration: none; }
.boton:active { transform: scale(0.98); }

.boton--primario {
    background: var(--color-marca);
    color: #FFF;
    box-shadow: var(--sombra-sm);
}
.boton--primario:hover { background: var(--color-marca-oscuro); }

.boton--secundario {
    background: var(--color-superficie);
    color: var(--color-texto);
    border: 1px solid var(--color-borde);
}
.boton--secundario:hover { background: var(--color-superficie-suave); }

.boton--fantasma { color: var(--color-texto-medio); }
.boton--fantasma:hover { background: var(--color-superficie-suave); }

.boton--pequeno { height: 32px; padding: 0 var(--esp-3); font-size: var(--texto-xs); }

.boton__icono { width: 16px; height: 16px; }

/* --- Tarjeta -------------------------------------------------------------- */

.tarjeta {
    display: flex;
    flex-direction: column;
    background: var(--color-superficie);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-lg);
    box-shadow: var(--sombra-sm);
    overflow: hidden;
    transition: box-shadow var(--transicion), border-color var(--transicion);
}
.tarjeta:hover {
    box-shadow: var(--sombra-hover);
    border-color: var(--color-marca-claro);
}

.tarjeta__cabecera {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    padding: var(--esp-5) var(--esp-5) var(--esp-4);
    border-bottom: 1px solid var(--color-borde-suave);
    margin-bottom: var(--esp-4);
}
.tarjeta__titulo {
    font-size: var(--texto-md);
    font-weight: var(--peso-semi);
    letter-spacing: -0.01em;
}
.tarjeta__accion {
    margin-left: auto;
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
}
.tarjeta__cuerpo  { flex: 1; padding: 0 var(--esp-5); }
.tarjeta__cuerpo--sin-espacio { padding: 0; }
.tarjeta__pie {
    padding: var(--esp-4) var(--esp-5);
    text-align: center;
}
.tarjeta__pie a { font-size: var(--texto-sm); font-weight: var(--peso-medio); }

/* --- Tarjeta KPI ----------------------------------------------------------
   Fila de 6 métricas del mockup. El icono lleva el hue semántico; la cifra
   siempre es del color de texto base — el color no debe competir con el dato. */

.kpi-fila {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--esp-4);
    margin-bottom: var(--esp-5);
}

.kpi {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--esp-3);
    padding: var(--esp-5);
    background: var(--color-superficie);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-lg);
    box-shadow: var(--sombra-sm);
    overflow: hidden;
    transition: transform var(--transicion), box-shadow var(--transicion), border-color var(--transicion);
}
.kpi::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 3px;
    background: var(--kpi-acento, var(--color-marca));
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--transicion);
}
.kpi:hover {
    transform: translateY(-3px);
    box-shadow: var(--sombra-hover);
}
.kpi:hover::before { transform: scaleX(1); }

.kpi:has(.acento-azul)    { --kpi-acento: var(--color-azul); }
.kpi:has(.acento-verde)   { --kpi-acento: var(--color-verde); }
.kpi:has(.acento-violeta) { --kpi-acento: var(--color-violeta); }
.kpi:has(.acento-ambar)   { --kpi-acento: var(--color-ambar); }
.kpi:has(.acento-rojo)    { --kpi-acento: var(--color-rojo); }
.kpi:has(.acento-cian)    { --kpi-acento: var(--color-cian); }

.kpi__superior { display: flex; align-items: center; gap: var(--esp-3); }

.kpi__icono {
    display: grid;
    place-items: center;
    width: 38px; height: 38px;
    border-radius: var(--radio-lg);
    flex-shrink: 0;
}
.kpi__icono svg { width: 18px; height: 18px; }

.kpi__etiqueta {
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    color: var(--color-texto-medio);
    line-height: 1.35;
}

.kpi__valor {
    font-size: var(--texto-xl);
    font-weight: var(--peso-bold);
    letter-spacing: -0.03em;
    font-variant-numeric: tabular-nums;
}

.kpi__variacion {
    display: flex;
    align-items: center;
    gap: var(--esp-1);
    font-size: var(--texto-xs);
    color: var(--color-texto-tenue);
}
.kpi__variacion strong { font-weight: var(--peso-semi); }
/* Sube/baja se codifica con flecha + color: nunca solo con color (daltonismo). */
.kpi__variacion--sube  strong { color: var(--texto-verde); }
.kpi__variacion--baja  strong { color: var(--texto-rojo); }

.kpi__grafico { height: 34px; width: 100%; }
.kpi__grafico path.kpi__grafico-linea { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.kpi__grafico path.kpi__grafico-area { stroke: none; }

/* Modificadores de hue para el icono. */
.acento-azul    { background: var(--bg-azul);    color: var(--color-azul); }
.acento-verde   { background: var(--bg-verde);   color: var(--color-verde); }
.acento-violeta { background: var(--bg-violeta); color: var(--color-violeta); }
.acento-ambar   { background: var(--bg-ambar);   color: var(--color-ambar); }
.acento-rojo    { background: var(--bg-rojo);    color: var(--color-rojo); }
.acento-cian    { background: var(--bg-cian);    color: var(--color-cian); }
.acento-neutro  { background: var(--bg-neutro);  color: var(--color-texto-tenue); }

/* --- Rejilla del dashboard -----------------------------------------------
   Mobile-first: apilado. En pantallas anchas se reconstruye la composición
   asimétrica del mockup: cada FILA declara sus propias proporciones, porque
   no son dos columnas fijas de ancho/estrecho — la fila 3 del mockup invierte
   qué lado es ancho (Actividad reciente estrecha a la izquierda, Resumen
   económico ancho a la derecha). Una sola rejilla de 2 columnas para toda la
   página no puede producir eso; una rejilla por fila, sí (ver §6). */

.fila-dashboard {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--esp-4);
    align-items: start;
    margin-bottom: var(--esp-4);
}
.fila-dashboard:last-child { margin-bottom: 0; }

/* --- Tabla ---------------------------------------------------------------- */

/* Envoltorio con scroll propio: la tabla nunca desborda el body. */
.tabla-scroll { width: 100%; overflow-x: auto; }

.tabla {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--texto-sm);
    white-space: nowrap;
}

.tabla thead th {
    padding: var(--esp-3) var(--esp-5);
    background: var(--color-superficie-suave);
    border-block: 1px solid var(--color-borde);
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    color: var(--color-texto-medio);
    text-align: left;
}

.tabla tbody td {
    padding: var(--esp-4) var(--esp-5);
    border-bottom: 1px solid var(--color-borde-suave);
    vertical-align: middle;
}
.tabla tbody tr:last-child td { border-bottom: none; }
.tabla tbody tr:hover { background: var(--color-superficie-suave); }

.tabla__principal { font-weight: var(--peso-medio); white-space: normal; min-width: 160px; }
.tabla__tenue     { color: var(--color-texto-tenue); white-space: normal; }
.tabla__codigo    { font-weight: var(--peso-semi); color: var(--color-marca); }
.tabla__numero    { text-align: right; font-variant-numeric: tabular-nums; }
.tabla__meta      { font-size: var(--texto-xs); color: var(--color-texto-tenue); margin-top: 2px; }
.tabla__acciones  { display: flex; gap: var(--esp-2); align-items: center; }

/* Fila con una incidencia real que requiere atención (fichaje con incidencia,
   ausencia sin justificar...) — antes `style="background: #fff5f5;"` suelto. */
.tabla tbody tr.tabla__fila--alerta          { background: var(--bg-rojo); }
.tabla tbody tr.tabla__fila--alerta:hover    { background: #FEE2E2; }

/* --- Badge de estado ------------------------------------------------------
   Mapea 1:1 con el ENUM `obras.estado_obra`. */

.badge {
    display: inline-flex;
    align-items: center;
    padding: var(--esp-1) var(--esp-3);
    border-radius: var(--radio-full);
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    white-space: nowrap;
}
.badge--ejecucion   { background: var(--color-marca-claro); color: var(--color-marca-texto); }
.badge--planificada { background: var(--bg-neutro);   color: var(--color-texto-medio); }
.badge--no-empezada { background: var(--bg-neutro);   color: var(--color-texto-tenue); }
.badge--revision    { background: var(--bg-ambar);    color: #92400E; }
.badge--parada      { background: var(--bg-rojo);     color: #991B1B; }
.badge--finalizada  { background: var(--bg-verde);    color: #065F46; }
.badge--cerrada     { background: var(--bg-neutro);   color: var(--color-texto-medio); }

/* Estado derivado de una certificación (Html::claseEstadoCertificacion). */
.badge--firmada     { background: var(--bg-azul);     color: var(--color-marca-texto); }

/* Prioridad de vencimientos: Alta / Media / Baja. */
.badge--alta  { background: var(--bg-rojo);   color: #991B1B; }
.badge--media { background: var(--bg-ambar);  color: #92400E; }
.badge--baja  { background: var(--bg-neutro); color: var(--color-texto-medio); }

/* --- Barra de progreso ---------------------------------------------------- */

.progreso { display: flex; align-items: center; gap: var(--esp-3); min-width: 120px; }
.progreso__pista {
    flex: 1;
    height: 6px;
    background: var(--color-borde);
    border-radius: var(--radio-full);
    overflow: hidden;
}
.progreso__relleno {
    height: 100%;
    background: var(--color-marca);
    border-radius: var(--radio-full);
}
.progreso__valor {
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    font-variant-numeric: tabular-nums;
    min-width: 32px;
}

/* --- Lista de eventos (actividad, vencimientos, documentos, incidencias) --- */

/* "Documentación y validaciones" a 2 columnas (certificaciones | facturas de
   compra), como el mockup. Apilado en móvil: dos listas largas en paralelo
   no caben en una pantalla estrecha. */
.documentacion-columnas {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0 var(--esp-6);
}
@media (min-width: 40em) {
    .documentacion-columnas { grid-template-columns: 1fr 1fr; }
}

.lista-eventos { list-style: none; display: grid; }

.evento {
    display: flex;
    align-items: flex-start;
    gap: var(--esp-3);
    padding: var(--esp-3) 0;
    border-bottom: 1px solid var(--color-borde-suave);
}
.evento:last-child { border-bottom: none; }

/* Notificación sin leer (notificaciones/index.php): franja lateral con el
   mismo azul de marca que usa .rail__enlace--activo, sin inventar un color. */
.evento--sin-leer {
    background: var(--color-superficie-suave);
    border-left: 3px solid var(--color-marca);
    padding-left: var(--esp-3);
    margin-left: calc(var(--esp-3) * -1);
    border-radius: var(--radio-sm);
}

.evento__icono {
    display: grid;
    place-items: center;
    width: 30px; height: 30px;
    border-radius: var(--radio-md);
    flex-shrink: 0;
}
.evento__icono svg { width: 15px; height: 15px; }

.evento__cuerpo { flex: 1; min-width: 0; }
.evento__titulo {
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    line-height: 1.4;
}
/* display:block porque se usa tanto en <p> como en <span> dentro de celdas. */
.evento__meta {
    display: block;
    font-size: var(--texto-xs);
    font-weight: var(--peso-normal);
    color: var(--color-texto-tenue);
    margin-top: 2px;
}
.evento__lateral {
    font-size: var(--texto-xs);
    color: var(--color-texto-tenue);
    white-space: nowrap;
    flex-shrink: 0;
}

/* Punto de estado con etiqueta (Pendiente revisión / Pendiente firma). */
.punto-estado {
    display: inline-flex;
    align-items: center;
    gap: var(--esp-2);
    font-size: var(--texto-xs);
    font-weight: var(--peso-medio);
    white-space: nowrap;
}
.punto-estado::before {
    content: "";
    width: 6px; height: 6px;
    border-radius: var(--radio-full);
    background: currentColor;
    flex-shrink: 0;
}
.punto-estado--revision  { color: var(--color-marca); }
.punto-estado--firma     { color: var(--texto-rojo); }
.punto-estado--pendiente { color: var(--texto-ambar); }
.punto-estado--ok        { color: var(--texto-verde); }
.punto-estado--tenue     { color: var(--color-texto-tenue); }

/* --- Estado vacío ---------------------------------------------------------
   Una pantalla vacía es una invitación a actuar, no un mensaje de error. */

.vacio {
    display: grid;
    place-items: center;
    gap: var(--esp-2);
    padding: var(--esp-8) var(--esp-4);
    text-align: center;
}
.vacio__icono { width: 32px; height: 32px; color: var(--color-texto-tenue); }
.vacio__titulo { font-size: var(--texto-sm); font-weight: var(--peso-semi); }
.vacio__texto  { font-size: var(--texto-xs); color: var(--color-texto-tenue); max-width: 32ch; }

/* --- Cuadrícula semanal (panel "Planificación semanal") -------------------
   7 columnas (lun-dom) × 4 filas (categorías). Cada celda es un conteo, no
   una magnitud continua: se codifica con un punto de tamaño proporcional en
   vez de una barra, porque son valores pequeños (0-¿20?) donde una escala de
   área discreta se lee más rápido que comparar longitudes de barra. */

/* Columnas: categoría | total de la semana | 7 días. El total va justo
   después de la etiqueta (como en el mockup), no al final. */
.cuadricula-semanal { display: grid; gap: var(--esp-1); }

.cuadricula-semanal__cabecera,
.cuadricula-semanal__fila {
    display: grid;
    grid-template-columns: 88px 28px repeat(7, 1fr);
    align-items: center;
    gap: var(--esp-2);
}

.cuadricula-semanal__cabecera {
    padding-bottom: var(--esp-2);
    border-bottom: 1px solid var(--color-borde);
}
.cuadricula-semanal__dia {
    display: flex;
    justify-content: center;
}
.cuadricula-semanal__dia-etiqueta {
    padding: 2px var(--esp-2);
    border-radius: var(--radio-full);
    font-size: var(--texto-2xs);
    font-weight: var(--peso-semi);
    color: var(--color-texto-tenue);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
/* Columna de "hoy": el mockup la marca con una píldora oscura en la
   cabecera, distinta de cualquier otro día. */
.cuadricula-semanal__dia--hoy .cuadricula-semanal__dia-etiqueta {
    background: var(--color-rail);
    color: var(--color-rail-texto-activo);
}

.cuadricula-semanal__fila { padding: var(--esp-2) 0; }
.cuadricula-semanal__fila:not(:last-child) { border-bottom: 1px solid var(--color-borde-suave); }

.cuadricula-semanal__categoria {
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    color: var(--color-texto);
}

.cuadricula-semanal__total {
    font-size: var(--texto-sm);
    font-weight: var(--peso-semi);
    color: var(--color-texto-medio);
    font-variant-numeric: tabular-nums;
}

.cuadricula-semanal__celda { display: grid; place-items: center; }

/* El punto: su TAMAÑO (no solo su color) codifica el conteo, así que la
   información sobrevive en escala de grises / CVD total. --escala la fija
   la vista según el máximo real de la semana (nunca un valor fijo). El HUE
   identifica la categoría de la fila -- 4 acentos fijos, nunca ciclados
   arbitrariamente (misma regla que cualquier paleta categórica de la app);
   rojo/verde quedan fuera porque ya llevan significado de estado en el
   resto del dashboard. */
.cuadricula-semanal__punto {
    width: var(--escala, 8px);
    height: var(--escala, 8px);
    border-radius: var(--radio-full);
    background: var(--color-marca);
}
.cuadricula-semanal__celda--vacia .cuadricula-semanal__punto {
    width: 4px;
    height: 4px;
    background: var(--color-borde);
}
.cuadricula-semanal__punto--montaje       { background: var(--color-azul); }
.cuadricula-semanal__punto--instalaciones { background: var(--color-cian); }
.cuadricula-semanal__punto--acabados      { background: var(--color-ambar); }
.cuadricula-semanal__punto--gestion       { background: var(--color-violeta); }

/* La columna de "hoy" siempre en tinta oscura, sea cual sea la categoría:
   distingue "hoy" de "qué tipo de trabajo es" en el mismo golpe de vista. */
.cuadricula-semanal__celda--hoy .cuadricula-semanal__punto:not(.cuadricula-semanal__punto--vacia) {
    background: var(--color-rail);
}

/* Fila de 4 cifras (Compras/Costes/Facturado/Cobrado) encima de la gráfica de
   barras del "Resumen económico" — el total del periodo actual de cada serie,
   con su variación frente al periodo anterior. Mismo patrón que .kpi__valor/
   .kpi__variacion, en formato compacto para caber en fila. */
.stats-resumen {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--esp-4);
    margin-bottom: var(--esp-5);
}
.stats-resumen__item { display: grid; gap: var(--esp-1); }
.stats-resumen__etiqueta {
    font-size: var(--texto-sm);
    color: var(--color-texto-medio);
}
.stats-resumen__valor {
    font-size: var(--texto-lg);
    font-weight: var(--peso-bold);
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}
.stats-resumen__variacion {
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
}
.stats-resumen__variacion--sube { color: var(--texto-verde); }
.stats-resumen__variacion--baja { color: var(--texto-rojo); }

/* --- Gráfica de barras (panel "Resumen económico") -------------------------
   4 series agrupadas por trimestre. Especificación de marca (skill dataviz):
   barras ≤24px de grosor, extremo redondeado de 4px, base cuadrada, hueco de
   2px en el color de superficie entre barras contiguas — nunca un borde. */

.grafica-barras {
    display: grid;
    grid-template-columns: 40px 1fr;
    gap: var(--esp-3);
}

.grafica-barras__eje {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding-bottom: 28px;   /* dejar sitio a las etiquetas de trimestre */
    font-size: var(--texto-2xs);
    color: var(--color-texto-tenue);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.grafica-barras__lienzo {
    display: flex;
    align-items: flex-end;
    gap: var(--esp-4);
    height: 220px;
    border-bottom: 1px solid var(--color-borde);   /* línea base, hairline */
}

.grafica-barras__grupo {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 2px;               /* el hueco de 2px entre barras contiguas */
    flex: 1;
    height: 100%;
    position: relative;
}

.grafica-barras__barra {
    width: 20px;             /* ≤ 24px, spec de la skill */
    max-width: 24px;
    border-radius: 4px 4px 0 0;   /* extremo redondeado, base cuadrada */
    transition: opacity var(--transicion);
}
.grafica-barras__barra:hover { opacity: 0.85; }

.grafica-barras__barra--compras   { background: var(--color-azul); }
.grafica-barras__barra--costes    { background: var(--color-rojo); }
.grafica-barras__barra--facturado { background: var(--color-verde); }
.grafica-barras__barra--cobrado   { background: var(--color-cian); }

.grafica-barras__etiqueta-grupo {
    position: absolute;
    bottom: -24px;
    left: 0;
    right: 0;
    text-align: center;
    font-size: var(--texto-2xs);
    font-weight: var(--peso-medio);
    color: var(--color-texto-tenue);
}

/* Leyenda: obligatoria a partir de 2 series (aquí hay 4). El texto lleva
   tinta de texto — el color de la serie lo lleva únicamente el cuadrado. */
.grafica-barras__leyenda {
    display: flex;
    flex-wrap: wrap;
    gap: var(--esp-4);
    margin-top: var(--esp-6);
    padding-top: var(--esp-4);
    border-top: 1px solid var(--color-borde-suave);
}
.grafica-barras__item-leyenda {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    font-size: var(--texto-xs);
    font-weight: var(--peso-medio);
    color: var(--color-texto-medio);
}
.grafica-barras__cuadro-leyenda {
    width: 10px;
    height: 10px;
    border-radius: 2px;
    flex-shrink: 0;
}
.grafica-barras__cuadro-leyenda--compras   { background: var(--color-azul); }
.grafica-barras__cuadro-leyenda--costes    { background: var(--color-rojo); }
.grafica-barras__cuadro-leyenda--facturado { background: var(--color-verde); }
.grafica-barras__cuadro-leyenda--cobrado   { background: var(--color-cian); }

/* --- Feed de actividad (panel "Actividad reciente") ------------------------
   Reutiliza .avatar/.evento__meta ya existentes; solo añade lo específico
   del feed cronológico. */

.feed-actividad { list-style: none; display: grid; }

.feed-actividad__item {
    display: flex;
    align-items: flex-start;
    gap: var(--esp-3);
    padding: var(--esp-3) 0;
    border-bottom: 1px solid var(--color-borde-suave);
}
.feed-actividad__item:last-child { border-bottom: none; }

.feed-actividad__cuerpo { flex: 1; min-width: 0; }
.feed-actividad__texto {
    font-size: var(--texto-sm);
    line-height: 1.4;
}
.feed-actividad__texto strong { font-weight: var(--peso-semi); }

.feed-actividad__tiempo {
    font-size: var(--texto-xs);
    color: var(--color-texto-tenue);
    white-space: nowrap;
    flex-shrink: 0;
}

/* --- Alerta --------------------------------------------------------------- */

.alerta {
    display: flex;
    align-items: flex-start;
    gap: var(--esp-3);
    padding: var(--esp-3) var(--esp-4);
    border-radius: var(--radio-md);
    font-size: var(--texto-sm);
    margin-bottom: var(--esp-4);
}
.alerta--error   { background: var(--bg-rojo);  color: #991B1B; }
.alerta--exito   { background: var(--bg-verde); color: #065F46; }
.alerta--aviso   { background: var(--bg-ambar); color: #92400E; }
.alerta--info    { background: var(--bg-azul);  color: var(--color-marca-texto); }

/* --- Filtro de empresa ----------------------------------------------------
   El grupo es multiempresa: por defecto se ve la actividad consolidada y este
   control acota a una sociedad. */

.filtro {
    display: inline-flex;
    align-items: center;
    gap: var(--esp-2);
    height: 40px;
    padding: 0 var(--esp-3);
    background: var(--color-superficie);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-md);
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    color: var(--color-texto);
    cursor: pointer;
}
.filtro:hover { background: var(--color-superficie-suave); }
.filtro__icono { width: 16px; height: 16px; color: var(--color-texto-tenue); }

/* El filtro es un <select> real: funciona sin JS y es accesible por teclado.
   Se le quita la apariencia nativa y se dibuja la flecha como fondo. */
select.filtro {
    appearance: none;
    padding-right: var(--esp-8);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394A3B8' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--esp-3) center;
    background-size: 14px;
}

/* Selector de rango de fechas de la cabecera del dashboard. Decorativo por
   ahora: ningún panel filtra todavía por rango arbitrario (cada uno usa su
   propia ventana fija -- semana en curso, mes en curso, últimos 6 meses),
   así que no lleva lógica detrás. Construido para que sea trivial de cablear
   el día que se añada ese filtro, sin rehacer el marcado. */
.filtro--fecha {
    gap: var(--esp-3);
    font-variant-numeric: tabular-nums;
}

/* Estado inerte compartido por todo control "aún no disponible" (el selector
   de fechas de arriba, "Conectar calendario", el selector de periodo del
   Resumen económico): atenuado y con el cursor por defecto, para que se lea
   como pendiente a propósito y no como un botón roto. */
button:disabled,
select:disabled {
    opacity: 0.55;
    cursor: default;
}
select:disabled:hover,
button:disabled:hover { background: inherit; }

/* --- Campos de formulario ------------------------------------------------- */

.campo { display: grid; gap: var(--esp-2); }

.campo__etiqueta {
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    color: var(--color-texto-medio);
}

.campo__control {
    width: 100%;
    height: 42px;
    padding: 0 var(--esp-3);
    background: var(--color-superficie);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-md);
    font-size: var(--texto-base);
    transition: border-color var(--transicion), box-shadow var(--transicion);
}
.campo__control:focus {
    border-color: var(--color-marca);
    outline: none;
    box-shadow: 0 0 0 3px var(--color-marca-claro);
}
.campo__control[aria-invalid="true"] { border-color: var(--color-rojo); }
.campo__control--textarea { height: auto; min-height: 88px; padding: var(--esp-2) var(--esp-3); resize: vertical; }

/* --- Campo horizontal (etiqueta + control corto en la misma fila) ---------
   Para valores cortos (un número, un toggle): un <select> de dirección larga
   necesita su propia fila entera, pero forzar la misma anchura a un campo de
   2 caracteres solo deja espacio vacío alrededor. */
.campo--horizontal { display: flex; align-items: center; justify-content: space-between; gap: var(--esp-3); }
.campo--horizontal .campo__etiqueta { flex-shrink: 0; }

/* --- Selector compacto de horas ("Fichar horas") ---------------------------
   El <input type="number"> real sigue enviándose tal cual (funciona sin JS,
   ver app.js) — esto solo lo envuelve en un stepper -/+ de ancho fijo en vez
   de un <input> suelto estirado al 100% para 1-2 dígitos. */
.campo__horas-selector {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-md);
    background: var(--color-superficie);
    overflow: hidden;
}
.campo__horas-boton {
    width: 36px; height: 42px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--texto-lg);
    font-weight: var(--peso-medio);
    color: var(--color-marca-texto);
    background: var(--color-superficie-suave);
    transition: background var(--transicion);
}
.campo__horas-boton:hover { background: var(--color-marca-claro); }
.campo__horas-boton:active { transform: scale(0.94); }
.campo__horas-valor {
    width: 56px;
    height: 42px;
    border: none;
    border-left: 1px solid var(--color-borde);
    border-right: 1px solid var(--color-borde);
    text-align: center;
    font-size: var(--texto-base);
    font-weight: var(--peso-bold);
    color: var(--color-texto);
    -moz-appearance: textfield;
    appearance: textfield;
}
.campo__horas-valor:focus { outline: none; background: var(--color-marca-claro); }
.campo__horas-valor::-webkit-outer-spin-button,
.campo__horas-valor::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.campo__horas-chips { display: flex; gap: var(--esp-2); margin-top: calc(var(--esp-2) * -1); }
.campo__horas-chip {
    flex: 1;
    height: 32px;
    border: 1px solid var(--color-borde-suave);
    border-radius: var(--radio-full);
    background: var(--color-superficie-suave);
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    color: var(--color-texto-medio);
    transition: background var(--transicion), border-color var(--transicion), color var(--transicion);
}
.campo__horas-chip:hover { border-color: var(--color-marca-claro); color: var(--color-marca-texto); }
.campo__horas-chip:active { transform: scale(0.96); }

.movil-horas-total { color: var(--color-texto-tenue); font-weight: var(--peso-semi); }

.campo__error {
    font-size: var(--texto-xs);
    font-weight: var(--peso-medio);
    color: var(--color-rojo);
}

/* --- Acceso ---------------------------------------------------------------
   El rail no existe aquí: el usuario aún no tiene identidad ni permisos. */

.login {
    display: grid;
    place-items: center;
    min-height: 100vh;
    padding: var(--esp-4);
    background: var(--color-rail);
}

.login__panel {
    width: 100%;
    max-width: 400px;
    padding: var(--esp-8);
    background: var(--color-superficie);
    border-radius: var(--radio-xl);
    box-shadow: var(--sombra-lg);
}

.login__marca {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--esp-2);
    margin-bottom: var(--esp-6);
}
.login__logo {
    display: grid;
    place-items: center;
    width: 38px; height: 38px;
    background: var(--color-rail);
    color: #FFF;
    border-radius: var(--radio-md);
    font-weight: var(--peso-bold);
}
/* El bloque de marca se reutiliza del rail, donde el texto es claro sobre
   fondo oscuro. Aquí el fondo es blanco: hay que invertirlo. */
.login__marca .rail__nombre        { color: var(--color-texto-tenue); }
.login__marca .rail__nombre strong { color: var(--color-texto); }

.login__titulo {
    font-size: var(--texto-lg);
    font-weight: var(--peso-bold);
    letter-spacing: -0.02em;
}
.login__subtitulo {
    font-size: var(--texto-sm);
    color: var(--color-texto-tenue);
    margin: var(--esp-1) 0 var(--esp-6);
}

.login__formulario { display: grid; gap: var(--esp-4); }
.login__enviar     { width: 100%; margin-top: var(--esp-2); }

.login__pie {
    margin-top: var(--esp-6);
    font-size: var(--texto-xs);
    color: var(--color-texto-tenue);
    text-align: center;
}

/* ============================================================================
   MÓDULO OBRAS (listado + ficha) — sin mockup propio, ver ObrasRepo.php
   ========================================================================== */

/* --- Enlace "Volver" -------------------------------------------------------- */

.volver {
    display: inline-flex;
    align-items: center;
    gap: var(--esp-1);
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    color: var(--color-texto-tenue);
    margin-bottom: var(--esp-2);
    transition: color var(--transicion);
}
.volver:hover { color: var(--color-marca); text-decoration: none; }
.volver__icono { width: 14px; height: 14px; transform: rotate(90deg); }

/* --- Filtros del listado ----------------------------------------------------- */

.filtros-listado {
    display: flex;
    flex-direction: column;
    gap: var(--esp-4);
    padding: var(--esp-5) var(--esp-5) var(--esp-4);
    border-bottom: 1px solid var(--color-borde);
}
@media (min-width: 64em) {
    .filtros-listado { flex-direction: row; align-items: center; justify-content: space-between; }
}

.pestanas-estado {
    display: flex;
    flex-wrap: wrap;
    gap: var(--esp-1);
}
.pestana-estado,
.selector-vista__opcion {
    transition: background var(--transicion), color var(--transicion);
}
.pestana-estado {
    display: inline-flex;
    align-items: center;
    gap: var(--esp-2);
    padding: var(--esp-2) var(--esp-3);
    border-radius: var(--radio-full);
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    color: var(--color-texto-medio);
    white-space: nowrap;
}
.pestana-estado:hover { background: var(--color-superficie-suave); text-decoration: none; }
.pestana-estado--activa {
    background: var(--color-marca-claro);
    color: var(--color-marca-texto);
    font-weight: var(--peso-semi);
}
.pestana-estado--activa:hover { background: var(--color-marca-claro); }
.pestana-estado__contador {
    padding: 1px var(--esp-2);
    background: rgba(15, 23, 42, 0.06);
    border-radius: var(--radio-full);
    font-size: var(--texto-2xs);
    font-variant-numeric: tabular-nums;
}
.pestana-estado--activa .pestana-estado__contador { background: rgba(37, 99, 235, 0.14); }

.buscador--listado { max-width: 320px; }

/* Fila de filtros secundarios (fecha/obra/empleado...) dentro de
   .filtros-listado — antes repetida como `style="display:flex;gap:..."` en
   Partes/Incidencias/Planificación. */
.filtros-extra {
    display: flex;
    gap: var(--esp-2);
    align-items: center;
    flex-wrap: wrap;
}
.filtros-extra .filtro--estrecho { max-width: 200px; }

/* Sub-navegación del módulo Compras y Almacén (ver partials/subnav-compras.php):
   el rail solo expone un enlace, esto es la navegación entre sus dos pantallas. */
.subnav-compras { margin-bottom: var(--esp-4); }

/* --- Selector de vista (Tabla/Kanban en Obras — mockups/2.png) ------------
   Segmentado de 2 opciones, mismo lenguaje visual que .pestana-estado pero
   con borde propio: no es un filtro de datos, es un modo de presentación. */
.selector-vista {
    display: inline-flex;
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-md);
    overflow: hidden;
    flex-shrink: 0;
    box-shadow: var(--sombra-sm);
}
.selector-vista__opcion {
    display: inline-flex;
    align-items: center;
    gap: var(--esp-2);
    padding: var(--esp-2) var(--esp-3);
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    color: var(--color-texto-medio);
    white-space: nowrap;
}
.selector-vista__opcion:hover { background: var(--color-superficie-suave); text-decoration: none; }
.selector-vista__opcion + .selector-vista__opcion { border-left: 1px solid var(--color-borde); }
.selector-vista__opcion--activa {
    background: var(--color-marca-claro);
    color: var(--color-marca-texto);
}
.selector-vista__opcion--activa:hover { background: var(--color-marca-claro); }

/* --- Tablero Kanban (Obras — mockups/2.png) -------------------------------
   Solo lectura: mover una tarjeta arrastrando exigiría una regla de negocio
   para el cambio de estado_obra que el cliente no ha confirmado (ver
   CLAUDE.md). Cada tarjeta enlaza a la misma ficha que la fila de tabla. */
.tablero-kanban {
    display: flex;
    gap: var(--esp-4);
    overflow-x: auto;
    padding: var(--esp-2) 0 var(--esp-1);
}
.tablero-kanban__columna {
    flex: 0 0 260px;
    background: var(--color-superficie-suave);
    border-radius: var(--radio-lg);
    padding: var(--esp-3);
}
.tablero-kanban__cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 var(--esp-1) var(--esp-3);
}
.tablero-kanban__contador {
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    color: var(--color-texto-tenue);
    font-variant-numeric: tabular-nums;
}
.tablero-kanban__tarjetas { display: grid; gap: var(--esp-2); }
.tablero-kanban__tarjeta {
    display: grid;
    gap: var(--esp-2);
    background: var(--color-superficie);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-md);
    padding: var(--esp-3);
    box-shadow: var(--sombra-sm);
    color: inherit;
    transition: border-color var(--transicion), box-shadow var(--transicion), transform var(--transicion);
}
.tablero-kanban__tarjeta:hover {
    border-color: var(--color-marca-claro);
    box-shadow: var(--sombra-hover);
    transform: translateY(-2px);
    text-decoration: none;
}
.tablero-kanban__codigo {
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    color: var(--color-marca);
}
.tablero-kanban__vacia {
    padding: var(--esp-4) 0;
    text-align: center;
    font-size: var(--texto-xs);
    color: var(--color-texto-tenue);
}

/* --- Gráfica de dona (Obras por estado — mockups/1.png) -------------------
   Técnica estándar de SVG: circunferencia ≈100 vía r=15.9155, cada segmento
   es un stroke-dasharray "largo 100" con su stroke-dashoffset acumulado.
   Empieza a las 12h porque .grafica-dona__figura gira -90°, no el cálculo
   de offset (ver obras/index.php). currentColor + .acento-* (ya usado por
   .evento__icono) evita inventar una paleta nueva: cada hue ya pasó el
   validador de la skill dataviz cuando se fijó el sistema de diseño. */
.grafica-dona {
    display: flex;
    align-items: center;
    gap: var(--esp-8);
    flex-wrap: wrap;
    padding: var(--esp-4) 0;
}
.grafica-dona__figura-envoltorio {
    position: relative;
    width: 140px;
    height: 140px;
    flex-shrink: 0;
}
.grafica-dona__figura { width: 100%; height: 100%; transform: rotate(-90deg); }
.grafica-dona__pista { stroke: var(--color-borde); }
.grafica-dona__segmento {
    stroke: currentColor;
    stroke-linecap: butt;
    transition: stroke-dasharray var(--transicion);
}
.grafica-dona__centro {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    line-height: 1.2;
}
.grafica-dona__centro strong { font-size: var(--texto-xl); font-weight: var(--peso-bold); }
.grafica-dona__centro span { font-size: var(--texto-xs); color: var(--color-texto-tenue); }

.grafica-dona__leyenda { list-style: none; display: grid; gap: var(--esp-3); flex: 0 1 320px; min-width: 200px; max-width: 320px; }
.grafica-dona__leyenda li {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    font-size: var(--texto-sm);
}
.grafica-dona__punto {
    width: 8px; height: 8px;
    border-radius: var(--radio-full);
    background: currentColor;
    flex-shrink: 0;
}
.grafica-dona__punto--pista { background: var(--color-borde); }
.grafica-dona__etiqueta { flex: 1; color: var(--color-texto-medio); }
.grafica-dona__valor {
    font-weight: var(--peso-semi);
    font-variant-numeric: tabular-nums;
    min-width: 28px;
    text-align: right;
}
.grafica-dona__porcentaje {
    font-size: var(--texto-xs);
    color: var(--color-texto-tenue);
    font-variant-numeric: tabular-nums;
    min-width: 42px;
    text-align: right;
}

/* --- Calendario de Obras (mockups/2.png) ----------------------------------
   Cuadrícula lunes-domingo. Cada pastilla reutiliza directamente las clases
   .badge--* ya existentes (fondo+texto) combinadas con esta clase para el
   tamaño/recorte — sin redeclarar ningún color. */
.calendario-obras { border: 1px solid var(--color-borde-suave); border-radius: var(--radio-md); overflow: hidden; }
.calendario-obras__cabecera {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    background: var(--color-superficie-suave);
    border-bottom: 1px solid var(--color-borde-suave);
}
.calendario-obras__cabecera span {
    padding: var(--esp-2);
    text-align: center;
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    color: var(--color-texto-tenue);
}
.calendario-obras__semana { display: grid; grid-template-columns: repeat(7, 1fr); }
.calendario-obras__dia {
    min-height: 92px;
    padding: var(--esp-2);
    display: grid;
    gap: 3px;
    align-content: start;
    border-right: 1px solid var(--color-borde-suave);
    border-bottom: 1px solid var(--color-borde-suave);
}
.calendario-obras__semana .calendario-obras__dia:last-child { border-right: none; }
.calendario-obras__dia--fuera { background: var(--color-superficie-suave); }
.calendario-obras__dia--fuera .calendario-obras__numero { color: var(--color-texto-tenue); }
.calendario-obras__dia--hoy {
    background: var(--color-marca-claro);
    box-shadow: inset 0 0 0 1px var(--color-marca);
}
.calendario-obras__numero { font-size: var(--texto-xs); font-weight: var(--peso-semi); font-variant-numeric: tabular-nums; }
.calendario-obras__dia--hoy .calendario-obras__numero {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px; height: 20px;
    background: var(--color-marca);
    color: #FFF;
    border-radius: var(--radio-full);
}
.calendario-obras__pastilla {
    display: block;
    padding: 1px var(--esp-2);
    border-radius: var(--radio-sm);
    font-size: var(--texto-2xs);
    font-weight: var(--peso-semi);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: filter var(--transicion), transform var(--transicion);
}
.calendario-obras__pastilla:hover { text-decoration: none; filter: brightness(0.96); transform: translateX(1px); }
.calendario-obras__mas { font-size: var(--texto-2xs); color: var(--color-texto-tenue); }

@media (max-width: 40em) {
    .calendario-obras__cabecera span:nth-child(n+6),
    .calendario-obras__dia:nth-child(n+6) { display: none; } /* Fin de semana oculto en móvil: caben las 5 columnas laborables sin scroll horizontal. */
}

/* --- Semáforo ----------------------------------------------------------------
   El color nunca es el único portador de significado (daltonismo): el punto
   siempre lleva texto adyacente ("Verde"/"Pendiente"), nunca solo el color. */

.semaforo-punto {
    display: inline-flex;
    align-items: center;
    gap: var(--esp-2);
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    white-space: nowrap;
}
.semaforo-punto::before {
    content: "";
    width: 8px; height: 8px;
    border-radius: var(--radio-full);
    background: currentColor;
    flex-shrink: 0;
}
.semaforo-punto--verde     { color: var(--texto-verde); }
.semaforo-punto--pendiente { color: var(--texto-ambar); }
.semaforo-punto--grande {
    font-size: var(--texto-md);
    font-weight: var(--peso-bold);
}
.semaforo-punto--grande::before { width: 12px; height: 12px; }
.semaforo-tarjeta__icono + div .semaforo-punto--grande::before { display: none; }

.semaforo-tarjeta {
    padding: var(--esp-5);
    margin-bottom: var(--esp-4);
    border-left: 3px solid var(--texto-ambar);
    background: var(--bg-ambar);
}
.semaforo-tarjeta--verde {
    border-left-color: var(--texto-verde);
    background: var(--bg-verde);
}
.semaforo-tarjeta__cabecera {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    flex-wrap: wrap;
    margin-bottom: var(--esp-4);
}
.semaforo-tarjeta__icono {
    background: var(--color-superficie);
    color: var(--texto-ambar);
}
.semaforo-tarjeta--verde .semaforo-tarjeta__icono { color: var(--texto-verde); }

.semaforo-lista {
    list-style: none;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--esp-3);
}
.semaforo-item {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    padding: var(--esp-2) var(--esp-3);
    background: var(--bg-ambar);
    border-radius: var(--radio-md);
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    color: var(--texto-ambar);
}
.semaforo-item svg { width: 16px; height: 16px; flex-shrink: 0; }
.semaforo-item--ok {
    background: var(--bg-verde);
    color: var(--texto-verde);
}

/* --- Datos generales de la ficha ---------------------------------------------- */

.datos-obra {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--esp-4);
    padding: var(--esp-5) 0;
}
@media (min-width: 40em) {
    .datos-obra { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 64em) {
    .datos-obra { grid-template-columns: repeat(3, 1fr); }
}
.datos-obra__item { display: grid; gap: 2px; }
.datos-obra__etiqueta {
    font-size: var(--texto-xs);
    color: var(--color-texto-tenue);
}
.datos-obra__valor {
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    color: var(--color-texto);
}

/* Variante compacta de la fila de KPI, para métricas secundarias (3 en vez
   de 6, sin sparkline ni variación). */
.kpi-fila--compacta {
    grid-template-columns: 1fr;
    margin-bottom: var(--esp-4);
}
@media (min-width: 40em) {
    .kpi-fila--compacta { grid-template-columns: repeat(3, 1fr); }
}

/* --- Objetivos de horas (hitos) ------------------------------------------------ */

.lista-objetivos { list-style: none; display: grid; gap: var(--esp-4); }
.objetivo-item {
    padding-bottom: var(--esp-4);
    border-bottom: 1px solid var(--color-borde-suave);
    display: grid;
    gap: var(--esp-2);
}
.objetivo-item:last-child { border-bottom: none; padding-bottom: 0; }
.objetivo-item__cabecera {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--esp-3);
    flex-wrap: wrap;
}
.objetivo-item__partida {
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
}

/* El objetivo superado necesita su propio color de relleno (nunca solo el
   ancho de la barra): --rojo es del mismo acento categórico que el resto de
   "riesgo/urgente" en la app. */
.progreso__relleno--rojo { background: var(--color-rojo); }

/* --- Checklist documental ------------------------------------------------------ */

.checklist-bloque__titulo {
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-texto-tenue);
    margin: var(--esp-4) 0 var(--esp-2);
}
.checklist-bloque__titulo:first-child { margin-top: 0; }

/* --- Timeline (histórico de la obra) -------------------------------------------
   Línea vertical + puntos, patrón estándar de historial cronológico. */

.timeline { list-style: none; position: relative; }
.timeline__item {
    position: relative;
    padding: 0 0 var(--esp-5) var(--esp-6);
}
.timeline__item:last-child { padding-bottom: 0; }
.timeline__item::before {
    /* La línea vertical que conecta los puntos. */
    content: "";
    position: absolute;
    left: 5px;
    top: 14px;
    bottom: -4px;
    width: 1px;
    background: var(--color-borde);
}
.timeline__item:last-child::before { display: none; }
.timeline__punto {
    position: absolute;
    left: 0;
    top: 4px;
    width: 11px; height: 11px;
    border-radius: var(--radio-full);
    background: var(--color-superficie);
    border: 2px solid var(--color-marca);
}
.timeline__item:first-child .timeline__punto {
    background: var(--color-marca);
    box-shadow: 0 0 0 3px var(--color-marca-claro);
}
.timeline__titulo {
    font-size: var(--texto-sm);
    font-weight: var(--peso-semi);
}
.timeline__meta {
    font-size: var(--texto-xs);
    color: var(--color-texto-tenue);
    margin-top: var(--esp-1);
}

/* --- Galería de fotografías de obra -------------------------------------------
   En Fase 1 no se incrusta la imagen real (las rutas apuntan al servidor de
   ficheros, no a URLs web): cada tarjeta muestra un marcador + la ficha de la
   foto (momento, descripción, autor, fecha). Cuando exista el endpoint que
   sirve el binario, el marcador se sustituye por la miniatura real. */

.galeria-fotos {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--esp-4);
    padding: var(--esp-5) 0;
}
.foto-card {
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-md);
    overflow: hidden;
}
.foto-card__marco {
    display: grid;
    place-items: center;
    aspect-ratio: 4 / 3;
    background: var(--color-superficie-suave);
    color: var(--color-texto-tenue);
}
.foto-card__marco svg { width: 28px; height: 28px; }
.foto-card__pie {
    display: grid;
    gap: var(--esp-2);
    padding: var(--esp-3);
}
.foto-card__desc {
    font-size: var(--texto-sm);
    font-weight: var(--peso-medio);
    line-height: 1.35;
}

/* ============================================================================
   MÓDULO ESTUDIOS Y PRESUPUESTOS — sin mockup propio, ver EstudiosRepo.php
   ========================================================================== */

/* Árbol de capítulos → subcapítulos → partidas, formato Presto
   (formatos/Formato_presto_presupuesto.md). El sangrado por nivel es la
   única señal jerárquica que hace falta — nunca más de 4 tonos de fondo,
   para que un 5º nivel hipotético siga siendo legible en vez de degradarse
   a un gris indistinguible. */

.presto-arbol { display: grid; gap: var(--esp-3); }

.presto-capitulo {
    border: 1px solid var(--color-borde-suave);
    border-radius: var(--radio-md);
    overflow: hidden;
}
.presto-capitulo + .presto-capitulo { margin-top: var(--esp-3); }

/* Los subcapítulos anidados llevan su propio margen izquierdo — el sangrado
   es lo que comunica "esto pertenece a lo anterior", no el color. */
.presto-capitulo--nivel1 { margin-left: var(--esp-5); }
.presto-capitulo--nivel2 { margin-left: var(--esp-8); }
.presto-capitulo--nivel3 { margin-left: calc(var(--esp-8) + var(--esp-5)); }

.presto-capitulo__cabecera {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    flex-wrap: wrap;
    padding: var(--esp-3) var(--esp-4);
    background: var(--color-superficie-suave);
}
.presto-capitulo--nivel0 > .presto-capitulo__cabecera { background: var(--color-borde-suave); }

.presto-capitulo__codigo {
    font-family: var(--fuente-datos);
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    color: var(--color-texto-tenue);
    flex-shrink: 0;
}
.presto-capitulo__nombre {
    flex: 1;
    min-width: 160px;
    font-size: var(--texto-sm);
    font-weight: var(--peso-semi);
}
.presto-capitulo__dias {
    font-size: var(--texto-xs);
    color: var(--color-texto-tenue);
    white-space: nowrap;
}
.presto-capitulo__importe {
    font-size: var(--texto-sm);
    font-weight: var(--peso-bold);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Tabla de partidas dentro de un capítulo: mismo componente .tabla de
   siempre, pero más compacta (menos padding) porque va anidada. */
.presto-partidas-tabla th,
.presto-partidas-tabla td { padding: var(--esp-2) var(--esp-4); }

/* ============================================================================
   5. UTILIDADES
   ========================================================================== */

.u-oculto        { display: none !important; }
.u-numero        { font-variant-numeric: tabular-nums; }
.u-truncar       { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.u-sin-margen    { margin: 0 !important; }

/* --- Módulos específicos: Planificación ----------------------------------- */

.planificacion-obras-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: var(--esp-4);
}

.cuadrilla-card {
    display: flex;
    flex-direction: column;
    gap: var(--esp-3);
    background: var(--color-superficie);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-lg);
    padding: var(--esp-4);
    box-shadow: var(--sombra-sm);
    transition: box-shadow var(--transicion), border-color var(--transicion);
}
.cuadrilla-card:hover { box-shadow: var(--sombra-md); border-color: var(--color-borde); }

.cuadrilla-card__cabecera {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--esp-2);
}

.cuadrilla-regla-box {
    padding: var(--esp-2) var(--esp-3);
    border-radius: var(--radio-md);
    font-size: var(--texto-xs);
    background: var(--color-superficie-suave);
    border-left: 3px solid var(--color-marca);
}

.cuadrilla-form-inline {
    background: var(--color-superficie-suave);
    border: 1px dashed var(--color-borde);
    border-radius: var(--radio-md);
    padding: var(--esp-3);
    display: flex;
    flex-direction: column;
    gap: var(--esp-2);
}
.cuadrilla-fila {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--esp-3);
    background: var(--color-superficie);
    border: 1px solid var(--color-borde-suave);
    padding: var(--esp-2) var(--esp-3);
    border-radius: var(--radio-md);
    font-size: var(--texto-sm);
}
.cuadrilla-fila__persona { display: flex; flex-direction: column; }
.cuadrilla-fila__categoria { font-size: var(--texto-xs); color: var(--color-texto-tenue); }
.cuadrilla-fila__horas { font-weight: var(--peso-semi); font-size: var(--texto-xs); }

/* --- Utilidades de color semántico (usadas por KPIs derivados: "Al día" /
   "Revisión Administración", "Atención urgente" / "Sin alertas graves"...) --- */
.text-danger  { color: var(--texto-rojo); }
.text-warning { color: var(--texto-ambar); }
.text-success { color: var(--texto-verde); }

/* Prioridad de una incidencia (`incidencias_obra.prioridad`) — antes un mapa
   de hex sueltos por fila (`color: #dc2626;...`) en vez de tokens. */
.texto-prioridad--critica { color: var(--texto-rojo);  font-weight: var(--peso-bold); }
.texto-prioridad--alta    { color: var(--texto-ambar); font-weight: var(--peso-bold); }
.texto-prioridad--media   { color: var(--texto-azul);  font-weight: var(--peso-semi); }
.texto-prioridad--baja    { color: var(--color-texto-tenue); }

/* --- Botón-icono (acciones de fila: validar/eliminar/deshacer) ------------
   Antes cada uso repetía `style="border:none;background:none;color:..."` a
   mano — sin estado hover ni foco, y con colores hex sueltos que en algún
   caso ni coincidían con el token real (--color-violeta es #8B5CF6, no el
   #7c3aed que se usaba como fallback). Un componente único, con foco
   visible, evita que ese hueco de accesibilidad se repita fila a fila. */
.boton-icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: var(--radio-md);
    color: var(--color-texto-tenue);
    transition: background var(--transicion), color var(--transicion);
}
.boton-icono:hover { background: var(--color-superficie-suave); color: var(--color-texto); }
.boton-icono:focus-visible { outline: 2px solid var(--color-marca); outline-offset: 1px; }
.boton-icono svg { width: 16px; height: 16px; }
.boton-icono--exito:hover   { background: var(--bg-verde); color: var(--texto-verde); }
.boton-icono--peligro:hover { background: var(--bg-rojo);  color: var(--texto-rojo); }
.boton-icono--activo        { color: var(--texto-verde); }

/* --- Formulario (modales de alta/edición) ----------------------------------
   Sustituye las etiquetas/inputs con `style` repetido campo a campo en los 3
   modales de Partes/Incidencias. */
.formulario { display: grid; gap: var(--esp-4); }
.formulario__fila { display: grid; grid-template-columns: 1fr 1fr; gap: var(--esp-3); }
.formulario__grupo { display: grid; gap: 5px; }
.formulario__etiqueta {
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    color: var(--color-texto-medio);
}
.formulario .filtro,
.formulario textarea { width: 100%; }
.formulario textarea { font-family: inherit; resize: vertical; }
.formulario__pie {
    display: flex;
    gap: var(--esp-3);
    justify-content: flex-end;
    padding-top: var(--esp-1);
}
.formulario__casilla {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
    font-size: var(--texto-xs);
}
.formulario__casilla label { cursor: pointer; }
.formulario__caja {
    background: var(--color-superficie-suave);
    padding: var(--esp-4);
    border-radius: var(--radio-md);
}

/* --- Modal ------------------------------------------------------------------
   Único componente de superposición de la app (antes: 3 copias de
   `display:none/block` inline por JS — y bloqueadas por la CSP `script-src
   'self'`, ver CLAUDE.md). Entrada con blur de fondo + escala sutil: el
   momento "de firma" de esta pasada de diseño — se dispara desde
   app.js vía [data-abrir-modal]/[data-cerrar-modal], nunca `onclick`. */
.modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: grid;
    place-items: center;
    padding: var(--esp-4);
    background: rgba(11, 18, 32, 0.56); /* --color-rail a baja opacidad: de marca, no un negro genérico */
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 200ms ease, visibility 0s linear 200ms;
}
.modal--abierto {
    opacity: 1;
    visibility: visible;
    transition: opacity 200ms ease;
}
.modal__panel {
    width: 100%;
    max-width: 30rem;
    max-height: 90vh;
    overflow-y: auto;
    background: var(--color-superficie);
    border-radius: var(--radio-xl);
    box-shadow: var(--sombra-lg);
    transform: scale(0.96) translateY(10px);
    transition: transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.modal--abierto .modal__panel { transform: scale(1) translateY(0); }
.modal__panel--ancho { max-width: 38rem; }
.modal__cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--esp-3);
    padding: var(--esp-5) var(--esp-5) var(--esp-4);
    border-bottom: 1px solid var(--color-borde-suave);
}
.modal__titulo { font-size: var(--texto-md); font-weight: var(--peso-bold); }
.modal__cerrar {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border-radius: var(--radio-full);
    color: var(--color-texto-tenue);
    transition: background var(--transicion), color var(--transicion);
}
.modal__cerrar:hover { background: var(--color-superficie-suave); color: var(--color-texto); }
.modal__cerrar:focus-visible { outline: 2px solid var(--color-marca); outline-offset: 1px; }
/* Reutiliza el icono "mas" (+) girado 45° = ×, sin añadir un icono nuevo. */
.modal__cerrar svg { width: 18px; height: 18px; transform: rotate(45deg); }
.modal__cuerpo { padding: var(--esp-5); }

@media (prefers-reduced-motion: reduce) {
    .modal, .modal__panel { transition: none; }
}

/* ============================================================================
   6. RESPONSIVE (mobile-first)
   ========================================================================== */

/* --- ≥ 640px · tablet vertical ------------------------------------------- */
@media (min-width: 40em) {
    .contenido    { padding: var(--esp-6) var(--esp-6) var(--esp-10); }
    .topbar       { padding: 0 var(--esp-6); }
    .kpi-fila     { grid-template-columns: repeat(2, 1fr); }
    .usuario-menu__datos { display: block; }
}

/* --- ≥ 1024px · escritorio: aparece el rail fijo -------------------------- */
@media (min-width: 64em) {
    .rail {
        transform: none;
        transition: none;
    }
    .shell { margin-left: var(--ancho-rail); }

    /* El cajón y su velo dejan de existir. */
    .topbar__hamburguesa,
    .rail-velo { display: none; }

    .kpi-fila { grid-template-columns: repeat(3, 1fr); }

    /* Cada fila del dashboard: ancho a la izquierda, estrecho a la derecha
       por defecto; --invertida lo cambia (fila "Actividad reciente" /
       "Resumen económico" del mockup). */
    .fila-dashboard {
        grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    }
    .fila-dashboard--invertida {
        grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
    }
    .fila-dashboard > .tarjeta { min-width: 0; }
}

/* --- ≥ 1440px · pantallas anchas: las 6 KPI en una fila ------------------- */
@media (min-width: 90em) {
    .kpi-fila  { grid-template-columns: repeat(6, 1fr); }
    .contenido { padding: var(--esp-6) var(--esp-8) var(--esp-10); }
}

/* ============================================================================
   6.9 LAYOUT MÓVIL ("Mi día" — mockups/7.png)
   ----------------------------------------------------------------------------
   Sin rail: en 375px de ancho no cabe con nada más. Topbar mínima fija arriba
   + barra de pestañas fija abajo, mismo lenguaje visual que el resto de la
   app (tokens de :root, sin paleta nueva). Centrado con ancho máximo en
   escritorio para que la pantalla no quede absurdamente ancha si alguien la
   abre en un monitor — sigue siendo la misma app, no una vista aparte.
   ========================================================================== */

.movil-body {
    background: #F8FAFC linear-gradient(180deg, #EFF6FF 0%, #F8FAFC 240px) no-repeat;
    color: var(--color-texto);
    font-feature-settings: "cv02", "cv03", "cv04", "cv11";
}

.movil-topbar {
    position: sticky;
    top: 0;
    z-index: 30;
    height: 60px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 var(--esp-4);
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid rgba(226, 232, 240, 0.8);
    max-width: 480px;
    margin: 0 auto;
    box-shadow: 0 4px 20px rgba(15, 23, 42, 0.03);
}
.movil-topbar__marca {
    display: flex;
    align-items: center;
    gap: var(--esp-2);
}
.movil-topbar__marca img { height: 26px; }
.movil-topbar .campana {
    color: #0F172A;
    transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.movil-topbar .campana:active { transform: scale(0.9); }

.movil-contenido {
    max-width: 480px;
    margin: 0 auto;
    padding: var(--esp-4) var(--esp-4) 115px var(--esp-4);
    display: block;
}

.movil-tabbar {
    position: fixed;
    bottom: 20px; left: 16px; right: 16px;
    z-index: 40;
    height: 66px;
    display: flex;
    max-width: 440px;
    margin: 0 auto;
    background: rgba(255, 255, 255, 0.94);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border: 1px solid rgba(226, 232, 240, 0.9);
    border-radius: 38px;
    box-shadow: 0 16px 40px rgba(15, 23, 42, 0.16);
    padding: 0 10px;
}
.movil-tab {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    font-size: 10px;
    font-weight: 600;
    color: #94A3B8;
    transition: all 0.2s cubic-bezier(0.32, 0.72, 0, 1);
}
.movil-tab:hover { text-decoration: none; color: #0F172A; }
.movil-tab:active { transform: scale(0.92); }
.movil-tab__icono { width: 20px; height: 20px; }
.movil-tab--activa { color: var(--color-marca); font-weight: 700; }
.movil-tab--central { flex: 1; position: relative; }
.movil-btn-flotante {
    width: 54px;
    height: 54px;
    border-radius: 50%;
    background: linear-gradient(135deg, #0F172A 0%, #1E293B 100%);
    color: #FFFFFF;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: -24px auto 0;
    box-shadow: 0 10px 24px rgba(15, 23, 42, 0.35), 0 0 0 4px #FFFFFF;
    border: none;
    transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.25s ease;
    cursor: pointer;
}
.movil-btn-flotante:active { transform: scale(0.90); }

/* --- Componentes del Mockup 7 ---------------------------------------------- */
.movil-card-oscura {
    background: #0F172A;
    color: #FFFFFF;
    border-radius: var(--radio-lg);
    padding: var(--esp-4);
    margin-bottom: var(--esp-4);
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);
}
.movil-card-oscura__cabecera {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--esp-3);
    padding-bottom: var(--esp-2);
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.movil-card-oscura__titulo {
    font-size: var(--texto-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: #94A3B8;
    font-weight: var(--peso-semi);
}
.movil-card-oscura__fecha { font-size: var(--texto-xs); color: #94A3B8; }
.movil-card-oscura__grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--esp-2);
    text-align: center;
}
.movil-metric-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}
.movil-metric-col__icono {
    width: 32px; height: 32px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.1);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #38BDF8;
}
.movil-metric-col__icono--alerta { color: #FCA5A5; }
.movil-metric-col__svg { width: 16px; height: 16px; }
.movil-metric-col strong {
    display: block;
    font-size: var(--texto-md);
    font-weight: var(--peso-bold);
    color: #F8FAFC;
}
.movil-metric-col__valor-alerta { color: #F87171 !important; }
.movil-metric-col span {
    font-size: 10px;
    color: #94A3B8;
}

/* Baldosas cuadradas de accesos rápidos: grid fijo, sin scroll oculto */
.movil-tile-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 8px;
    margin-bottom: var(--esp-4);
}
.movil-tile-acceso {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 10px 4px;
    background: #FFFFFF;
    border: 1px solid var(--color-borde-suave);
    border-radius: var(--radio-md);
    font-size: 11px;
    font-weight: var(--peso-semi);
    color: var(--color-texto);
    text-align: center;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
}
.movil-tile-acceso:hover { text-decoration: none; transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0,0,0,0.08); }
.movil-tile-icon-box {
    width: 40px;
    height: 40px;
    border-radius: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.movil-tile-icon-box--azul { background: #EFF6FF; color: #2563EB; }
.movil-tile-icon-box--naranja { background: #FFFBEB; color: #D97706; }
.movil-tile-icon-box--violeta { background: #F3E8FF; color: #9333EA; }
.movil-tile-icon-box--verde { background: #F0FDF4; color: #16A34A; }
.movil-tile-icon-box--rojo { background: #FEF2F2; color: #DC2626; }

/* --- Ranking interno: podio ("Mis objetivos") ------------------------------ */
.movil-podium-row {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: var(--esp-3);
}
.movil-podium-card {
    flex: 1;
    background: #F8FAFC;
    border: 1px solid var(--color-borde-suave);
    border-radius: var(--radio-md);
    padding: var(--esp-3) var(--esp-2);
    text-align: center;
    min-width: 0;
}
.movil-podium-card--top1 {
    background: #FFFBEB;
    border-color: #FCD34D;
    transform: translateY(-8px);
    box-shadow: 0 4px 14px rgba(245, 158, 11, 0.15);
}
.movil-podium-card__puesto {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px; height: 20px;
    border-radius: 50%;
    background: #E2E8F0;
    color: #475569;
    font-size: 10px;
    font-weight: var(--peso-bold);
    margin-bottom: 4px;
}
.movil-podium-card__puesto--1 { width: 22px; height: 22px; font-size: 11px; background: #F59E0B; color: #FFF; box-shadow: 0 2px 6px rgba(245,158,11,0.4); }
.movil-podium-card__avatar { margin: 0 auto 4px; }
.movil-podium-card--top1 .movil-podium-card__avatar { border: 2px solid #FBBF24; }
.movil-podium-card__nombre {
    display: block;
    font-size: 11px;
    color: var(--color-texto);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.movil-podium-card--top1 .movil-podium-card__nombre { font-size: 12px; color: #78350F; }
.movil-podium-card__puntos { font-size: 10px; color: var(--color-texto-tenue); }
.movil-podium-card--top1 .movil-podium-card__puntos { font-size: 11px; color: #D97706; font-weight: var(--peso-bold); }

/* --- Hero de puntuación ("Mis objetivos") ----------------------------------- */
.movil-score-hero {
    background: linear-gradient(135deg, #0F172A 0%, #1E293B 100%);
    color: #FFF;
    border-radius: var(--radio-lg);
    padding: var(--esp-4) var(--esp-5);
    margin-bottom: var(--esp-4);
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.15);
}
.movil-score-hero__etiqueta {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--texto-xs);
    color: #94A3B8;
    font-weight: var(--peso-semi);
}
.movil-score-hero__icono { width: 14px; height: 14px; }
.movil-score-hero__valor {
    display: block;
    font-size: 28px;
    font-weight: var(--peso-bold);
    color: #F8FAFC;
    margin: 4px 0 2px;
}
.movil-score-hero__valor span { font-size: var(--texto-base); font-weight: var(--peso-normal); color: #94A3B8; }

/* --- Donut de cumplimiento de objetivos ------------------------------------- */
.movil-donut-fila { display: flex; align-items: center; gap: var(--esp-4); margin-bottom: var(--esp-4); }
.movil-donut { position: relative; width: 72px; height: 72px; flex-shrink: 0; }
.movil-donut__svg { transform: rotate(-90deg); }
.movil-donut__valor {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    font-size: var(--texto-sm);
    font-weight: var(--peso-bold);
    color: var(--color-texto);
}
.movil-donut-fila__texto strong { font-size: var(--texto-sm); color: var(--color-texto); display: block; margin-bottom: 2px; }
.movil-donut-fila__texto span { font-size: var(--texto-xs); color: var(--color-texto-tenue); }

.movil-desglose { display: grid; gap: var(--esp-2); }
.movil-desglose__cabecera { display: flex; justify-content: space-between; font-size: var(--texto-xs); margin-bottom: 3px; }
.movil-desglose__cabecera span { color: var(--color-texto-medio); font-weight: var(--peso-semi); }
.movil-desglose__cabecera strong { color: var(--color-texto); }
.movil-desglose__pista { width: 100%; height: 6px; background: #E2E8F0; border-radius: var(--radio-full); overflow: hidden; }
.movil-desglose__barra { height: 100%; border-radius: var(--radio-full); }
.movil-desglose__barra--verde  { background: var(--color-verde); }
.movil-desglose__barra--azul   { background: var(--color-marca); }
.movil-desglose__barra--ambar  { background: var(--color-ambar); }
.movil-desglose__barra--neutro { background: var(--color-texto-tenue); }

/* --- Tarjeta de métrica única (horas trabajadas) ---------------------------- */
.movil-tile-metrica__etiqueta { font-size: var(--texto-xs); color: var(--color-texto-tenue); display: block; margin-bottom: 2px; }
.movil-tile-metrica__valor { font-size: var(--texto-xl); font-weight: var(--peso-bold); color: var(--color-texto); }
.movil-tile-metrica__var { font-size: var(--texto-xs); font-weight: var(--peso-bold); display: block; margin-top: 2px; }
.movil-tile-metrica__var--positivo { color: var(--texto-verde); }
.movil-tile-metrica__var--negativo { color: var(--texto-rojo); }

/* --- Recompensa alcanzable --------------------------------------------------- */
.movil-recompensa {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--esp-3);
    padding: var(--esp-3);
    background: var(--bg-ambar);
    border: 1px solid #FDE68A;
    border-radius: var(--radio-md);
}
.movil-recompensa__icono {
    flex-shrink: 0;
    width: 36px; height: 36px;
    border-radius: 50%;
    background: #FFFFFF;
    color: #D97706;
    display: flex;
    align-items: center;
    justify-content: center;
}
.movil-recompensa__texto { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.movil-recompensa__texto strong { font-size: var(--texto-sm); color: #78350F; }
.movil-recompensa__texto span { font-size: 11px; color: #D97706; }
.movil-recompensa__puntos {
    flex-shrink: 0;
    font-size: var(--texto-xs);
    font-weight: var(--peso-bold);
    color: #D97706;
    background: #FFFFFF;
    padding: 4px 10px;
    border-radius: var(--radio-full);
    border: 1px solid #FCD34D;
}

/* --- Modal "Acciones rápidas" (botón + de la barra móvil) ------------------
   Único modal de la app con tratamiento "flotante": blur de fondo reforzado
   y panel en squircle grande, solo aquí (ámbito por #id, no toca `.modal`
   compartido por el resto de formularios de la app). El muelle de easing
   (cubic-bezier 0.34/1.56/0.64/1) es el mismo que ya usa `.movil-btn-flotante`
   y `.movil-tab` — se reutiliza la firma de movimiento existente, no se
   inventa una nueva. */
#modal-acciones-rapidas.modal--flotante {
    background: rgba(11, 18, 32, 0.7);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}
.modal__panel--flotante {
    max-width: 26rem;
    border-radius: 28px;
    box-shadow: 0 24px 60px rgba(15, 23, 42, 0.35), 0 2px 8px rgba(15, 23, 42, 0.08);
}
.modal__cabecera--flotante { border-bottom: none; padding-bottom: var(--esp-2); }
.movil-acciones-rapidas__subtitulo { font-size: var(--texto-xs); color: var(--color-texto-tenue); margin-top: 1px; }

.movil-acciones-rapidas { display: flex; flex-direction: column; gap: var(--esp-2); padding-top: var(--esp-1); }
.movil-accion-rapida {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    padding: var(--esp-3);
    background: var(--color-superficie);
    border: 1px solid var(--color-borde-suave);
    border-radius: 20px;
    color: var(--color-texto);
    transition: background 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
                border-color 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
                transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
                box-shadow 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.movil-accion-rapida:hover {
    text-decoration: none;
    background: var(--color-superficie-suave);
    border-color: var(--color-marca-claro);
    transform: translateY(-2px);
    box-shadow: 0 10px 24px rgba(15, 23, 42, 0.08);
}
.movil-accion-rapida:active { transform: scale(0.98) translateY(0); }
.movil-accion-rapida:hover .movil-accion-rapida__icono { transform: scale(1.06); }
.movil-accion-rapida:hover .movil-accion-rapida__flecha-caja { background: var(--color-marca); color: #FFF; transform: translateX(2px); }
.movil-accion-rapida__icono {
    flex-shrink: 0;
    width: 46px; height: 46px;
    border-radius: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.movil-accion-rapida__icono .icono { width: 22px; height: 22px; }
.movil-accion-rapida__icono--azul { background: var(--bg-azul); color: var(--color-marca-texto); box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.06); }
.movil-accion-rapida__icono--rojo { background: var(--bg-rojo); color: var(--texto-rojo); box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.06); }
.movil-accion-rapida__texto { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.movil-accion-rapida__texto strong { font-size: var(--texto-sm); font-weight: var(--peso-semi); }
.movil-accion-rapida__texto span { font-size: var(--texto-xs); color: var(--color-texto-tenue); }
.movil-accion-rapida__flecha-caja {
    flex-shrink: 0;
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--bg-neutro);
    color: var(--color-texto-tenue);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
                color 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
                transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.movil-accion-rapida__flecha { width: 14px; height: 14px; transform: rotate(-90deg); }

/* --- Cabecera "Mi día" (/mi-dia) ------------------------------------------- */
.movil-cabecera { display: flex; align-items: center; gap: var(--esp-3); margin-bottom: var(--esp-5); }
.movil-cabecera__texto { flex: 1; min-width: 0; }
.movil-cabecera__titulo { font-size: var(--texto-lg); font-weight: var(--peso-bold); line-height: 1.2; letter-spacing: -0.01em; }
.movil-cabecera__rol { font-size: var(--texto-xs); color: var(--color-texto-tenue); margin-top: 2px; }

.movil-estado-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    padding: 5px 10px;
    border-radius: var(--radio-full);
    font-size: var(--texto-2xs);
    font-weight: var(--peso-semi);
    white-space: nowrap;
}
.movil-estado-pill__punto { width: 6px; height: 6px; border-radius: 50%; }
.movil-estado-pill--activo { background: var(--bg-verde); color: var(--texto-verde); }
.movil-estado-pill--activo .movil-estado-pill__punto { background: var(--color-verde); }
.movil-estado-pill--neutro { background: var(--bg-neutro); color: var(--color-texto-medio); }
.movil-estado-pill--neutro .movil-estado-pill__punto { background: var(--color-texto-tenue); }

/* --- Bloques de sección genéricos ("Próxima tarea", listas) --------------- */
.movil-seccion { padding: var(--esp-4); margin-bottom: var(--esp-4); }
.movil-seccion__cabecera { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--esp-2); }
.movil-seccion__cabecera--suelta { margin-bottom: var(--esp-3); }
.movil-seccion__etiqueta {
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
    color: var(--color-texto-tenue);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.movil-seccion__subtitulo { font-size: var(--texto-sm); font-weight: var(--peso-bold); margin: 0; }
.movil-seccion__titulo { font-size: var(--texto-md); font-weight: var(--peso-semi); line-height: 1.3; margin-bottom: var(--esp-1); }
.movil-seccion__meta { margin-bottom: var(--esp-3); }
.movil-seccion__cta { width: 100%; }

/* --- Estado vacío reutilizable ---------------------------------------------- */
.movil-vacio { text-align: center; padding: var(--esp-4) var(--esp-2); }
.movil-vacio__icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px; height: 40px;
    border-radius: 50%;
    background: var(--bg-verde);
    color: var(--texto-verde);
    margin-bottom: var(--esp-3);
}
.movil-vacio__icono .icono { width: 20px; height: 20px; }
.movil-vacio__texto { font-size: var(--texto-sm); font-weight: var(--peso-semi); color: var(--color-texto); }
.movil-vacio__subtexto { font-size: var(--texto-xs); color: var(--color-texto-tenue); margin-top: 2px; }

/* --- Lista de obras del día -------------------------------------------------- */
.movil-lista-obras { display: flex; flex-direction: column; gap: var(--esp-2); margin-bottom: var(--esp-4); }
.movil-obra-fila {
    display: flex;
    align-items: center;
    gap: var(--esp-3);
    padding: var(--esp-3) var(--esp-4);
    background: var(--color-superficie);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-lg);
    box-shadow: var(--sombra-sm);
    color: var(--color-texto);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.movil-obra-fila:hover { text-decoration: none; transform: translateY(-1px); box-shadow: var(--sombra-md); }
.movil-obra-fila__icono {
    flex-shrink: 0;
    width: 36px; height: 36px;
    border-radius: var(--radio-md);
    background: var(--bg-azul);
    color: var(--color-marca-texto);
    display: flex;
    align-items: center;
    justify-content: center;
}
.movil-obra-fila__icono .icono { width: 18px; height: 18px; }
.movil-obra-fila__texto { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.movil-obra-fila__texto strong { font-size: var(--texto-sm); font-weight: var(--peso-semi); }
.movil-obra-fila__texto span { font-size: var(--texto-xs); color: var(--color-texto-tenue); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --- Cabecera de subpágina móvil (tareas/fichar/objetivos/notificaciones) -- */
.movil-encabezado { margin-bottom: var(--esp-4); }
.movil-encabezado__titulo { font-size: var(--texto-lg); font-weight: var(--peso-bold); letter-spacing: -0.01em; line-height: 1.2; }
.movil-encabezado__subtitulo { font-size: var(--texto-sm); color: var(--color-texto-tenue); margin-top: 2px; }

/* --- Tarjeta de tarea ("Mis tareas") ---------------------------------------- */
.movil-lista-tareas { display: flex; flex-direction: column; gap: var(--esp-3); }
.movil-tarea-card { padding: var(--esp-4); }
.movil-tarea-card__cabecera { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--esp-2); }
.movil-tarea-card__fecha { font-size: var(--texto-xs); color: var(--color-texto-tenue); font-weight: var(--peso-medio); }
.movil-tarea-card__titulo { font-size: var(--texto-base); font-weight: var(--peso-semi); line-height: 1.3; margin-bottom: var(--esp-1); }
.movil-tarea-card__obra { margin-bottom: var(--esp-3); }
.movil-tarea-card__obra a { color: var(--color-marca); font-weight: var(--peso-semi); }
.movil-tarea-card__estado { margin-bottom: var(--esp-3); }
.movil-tarea-card__accion { margin-top: var(--esp-1); }
.movil-tarea-card__boton { width: 100%; }
.movil-tarea-card__completada {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--esp-1);
    padding: var(--esp-2);
    background: var(--bg-verde);
    color: var(--texto-verde);
    border-radius: var(--radio-md);
    font-size: var(--texto-xs);
    font-weight: var(--peso-semi);
}
.movil-tarea-card__completada .icono { width: 14px; height: 14px; }

.movil-prioridad-pill {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: var(--radio-full);
    font-size: var(--texto-2xs);
    font-weight: var(--peso-bold);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}
.movil-prioridad-pill--critica { background: var(--color-rojo); color: #FFF; }
.movil-prioridad-pill--alta    { background: var(--bg-rojo);   color: var(--texto-rojo); }
.movil-prioridad-pill--media   { background: var(--bg-ambar);  color: var(--texto-ambar); }
.movil-prioridad-pill--baja    { background: var(--bg-neutro); color: var(--color-texto-medio); }

/* --- Centro de notificaciones móvil ---------------------------------------- */
.movil-notif-hero {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--esp-3);
    margin-bottom: var(--esp-4);
}
.movil-notif-card {
    position: relative;
    padding: var(--esp-4);
    border-radius: var(--radio-md);
    background: #FFFFFF;
    border-left: 4px solid var(--color-borde);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.movil-notif-card--urgente { border-left-color: #EF4444; }
.movil-notif-card--alerta  { border-left-color: #F59E0B; }
.movil-notif-card--info    { border-left-color: var(--color-marca); }
.movil-notif-card--leida   { opacity: 0.65; background: var(--color-superficie-suave); }

.movil-notif-card__top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--esp-2);
}
.movil-notif-card__titulo {
    font-size: var(--texto-base);
    font-weight: var(--peso-semi);
    line-height: 1.35;
    color: var(--color-texto);
    margin-bottom: var(--esp-1);
}
.movil-notif-card__mensaje {
    font-size: var(--texto-sm);
    color: var(--color-texto-medio);
    line-height: 1.45;
    margin-bottom: var(--esp-2);
}
.movil-notif-card__meta {
    font-size: var(--texto-xs);
    color: var(--color-texto-tenue);
    display: flex;
    align-items: center;
    gap: var(--esp-2);
}
.movil-notif-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #EF4444;
    box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.2);
}

/* --- Perfil móvil ---------------------------------------------------------- */

/* Hero card con gradiente oscuro premium y avatar central */
.movil-perfil-hero {
    background: linear-gradient(160deg, #0F172A 0%, #1E3A5F 60%, #0F172A 100%);
    color: #FFFFFF;
    border-radius: 24px;
    padding: 28px 20px 24px;
    margin-bottom: var(--esp-4);
    text-align: center;
    box-shadow: 0 16px 48px rgba(15, 23, 42, 0.22), inset 0 1px 0 rgba(255, 255, 255, 0.06);
    position: relative;
    overflow: hidden;
}
/* Orbe decorativo de fondo */
.movil-perfil-hero::before {
    content: '';
    position: absolute;
    top: -40px; right: -40px;
    width: 160px; height: 160px;
    background: radial-gradient(circle, rgba(56, 189, 248, 0.15) 0%, transparent 70%);
    pointer-events: none;
}

/* Avatar grande con doble anillo */
.movil-perfil-avatar-wrap {
    position: relative;
    display: inline-flex;
    margin-bottom: 16px;
}
.movil-perfil-avatar {
    width: 92px;
    height: 92px;
    border-radius: 50%;
    background: linear-gradient(135deg, #0284C7 0%, #0369A1 100%);
    color: #FFFFFF;
    font-size: 30px;
    font-weight: var(--peso-bold);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    object-fit: cover;
    border: 3px solid rgba(255, 255, 255, 0.12);
    box-shadow: 0 0 0 6px rgba(56, 189, 248, 0.18), 0 8px 20px rgba(0, 0, 0, 0.4);
    letter-spacing: -0.01em;
}
/* Indicador de estado activo sobre el avatar */
.movil-perfil-estado-dot {
    position: absolute;
    bottom: 4px; right: 4px;
    width: 18px; height: 18px;
    background: #22C55E;
    border-radius: 50%;
    border: 3px solid #0F172A;
    box-shadow: 0 2px 6px rgba(34, 197, 94, 0.5);
}

.movil-perfil-nombre {
    font-size: 22px;
    font-weight: 800;
    color: #FFFFFF;
    margin-bottom: 4px;
    letter-spacing: -0.02em;
    line-height: 1.2;
}
.movil-perfil-subtitulo {
    font-size: var(--texto-sm);
    color: #94A3B8;
    margin-bottom: var(--esp-4);
    font-weight: 500;
}
.movil-perfil-badge-puntos {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(245, 158, 11, 0.14);
    border: 1px solid rgba(245, 158, 11, 0.3);
    color: #FCD34D;
    padding: 6px 14px;
    border-radius: 999px;
    font-weight: 700;
    font-size: var(--texto-sm);
    margin-bottom: var(--esp-4);
}

/* 2 stats en fila separados por línea */
.movil-perfil-stat-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0;
    margin-top: 0;
    padding-top: var(--esp-4);
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    text-align: left;
}
.movil-perfil-stat-grid > div:first-child {
    padding-right: var(--esp-3);
    border-right: 1px solid rgba(255, 255, 255, 0.08);
}
.movil-perfil-stat-grid > div:last-child {
    padding-left: var(--esp-3);
}
.movil-perfil-stat-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #64748B;
    display: block;
    margin-bottom: 4px;
    font-weight: 600;
}
.movil-perfil-stat-val {
    font-size: var(--texto-sm);
    font-weight: 700;
    color: #F1F5F9;
}

/* Tarjeta de info con filas tipo lista */
.movil-perfil-info-item {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 0;
    border-bottom: 1px solid var(--color-borde-suave);
    transition: opacity 0.2s cubic-bezier(0.32, 0.72, 0, 1);
}
.movil-perfil-info-item:last-child { border-bottom: none; }
.movil-perfil-info-item:active { opacity: 0.7; }
.movil-perfil-info-icono {
    width: 40px;
    height: 40px;
    border-radius: 14px;
    background: #EFF6FF;
    color: #2563EB;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.movil-perfil-info-item:active .movil-perfil-info-icono {
    transform: scale(0.92);
}

/* Botón de cierre de sesión de nivel premium */
.movil-perfil-logout {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    padding: 0;
    height: 52px;
    background: rgba(239, 68, 68, 0.08);
    border: 1px solid rgba(239, 68, 68, 0.2);
    border-radius: 16px;
    color: #EF4444;
    font-size: var(--texto-sm);
    font-weight: 700;
    cursor: pointer;
    transition: all 0.2s cubic-bezier(0.32, 0.72, 0, 1);
    margin-top: var(--esp-2);
}
.movil-perfil-logout:active {
    transform: scale(0.97);
    background: rgba(239, 68, 68, 0.15);
}

/* ============================================================================
   7. IMPRESIÓN
   ========================================================================== */

@media print {
    .rail, .topbar, .rail-velo,
    .pagina-cabecera__acciones { display: none !important; }
    .shell   { margin-left: 0; }
    .tarjeta { border: 1px solid #CCC; box-shadow: none; break-inside: avoid; }
    body     { background: #FFF; }
}
