@charset "UTF-8";
/* ============================================================================
   PVM SAS · sintegrado — HOJA DE ESTILOS BASE  ("ACERO v2 / Grafito Humo")
   ----------------------------------------------------------------------------
   ERP de manufactura metalmecánica: fundición, soldadura, mecanizado, ensamble.
   Este archivo es la ÚNICA fuente de verdad visual del sistema. Todas las
   pantallas del ERP deben construirse con los tokens y componentes de aquí.

   Sin dependencias externas. La única fuente tipográfica remota (Google Fonts)
   se enlaza desde el <head> del HTML, NO desde este archivo.

   ----------------------------------------------------------------------------
   CÓMO CAMBIAR LA IDENTIDAD VISUAL
   Para reteñir todo el ERP basta con editar las SECCIONES 1 y 2 (los tokens).
   Ningún componente de la sección 5 en adelante lleva colores literales:
   todos leen variables. Si escribes un color en un componente, lo estás
   haciendo mal.

   ----------------------------------------------------------------------------
   NOMENCLATURA DE TOKENS
     --bg-*      superficies (0 = fondo de página … 3 = superficie elevada)
     --line-*    bordes y rejillas
     --ink-*     texto (1 principal, 2 secundario, 3 terciario)
     --acc*      acento primario (ámbar-cobre · "metal al rojo")
     --sec*      acento secundario (acero)
     --ok / --warn / --dang     estados semánticos
     --tex-*     micro-texturas de superficie (acabado mecanizado)
     --sh-*      sombras
     --f-*       familias tipográficas
     --sp-*      escala de espaciado (base 4px)
     --r-*       radios de esquina
     --tr-*      transiciones
     --nav-w / --bar-h / --maxw   alturas y anchos de layout

   ----------------------------------------------------------------------------
   ÍNDICE
     0.  DECISIÓN DE ARQUITECTURA DE TEMAS (leer antes de tocar nada)
     1.  TOKENS — TEMA CLARO · "GRAFITO HUMO"  (:root · PREDETERMINADO)
     2.  TOKENS — TEMA OSCURO · "ACERO"        ([data-theme="dark"])
     3.  RESET Y BASE
     4.  TRANSICIÓN DE TEMA
     5.  ACCESIBILIDAD Y FOCO
     6.  SISTEMA DE ICONOS (.ico)
     7.  BISEL TÉCNICO DE ESQUINA (.bisel)
     8.  ESQUELETO DE LAYOUT (.app / .main / .wrap)
     9.  APP BAR  (marca · buscador · acciones · conmutador de tema · usuario)
     10. NAVEGACIÓN LATERAL (.nav)
     11. ENCABEZADO DE PÁGINA (.hero / .eyebrow / .metaitem)
     12. BOTONES (.btn / .iconbtn)
     13. CHIPS, BADGES, TENDENCIAS Y PUNTOS DE ESTADO
     14. TARJETAS GENÉRICAS (.card)
     15. KPIs (.kpi) Y MICRO-GRÁFICAS (.viz)
     16. GRUPOS DE MÓDULOS (.grupo) Y TARJETAS DE MÓDULO (.mod)
     17. TABLAS (.tabla)
     18. PIE DE PÁGINA (.foot)
     19. MOVIMIENTO: @keyframes Y ENTRADA ESCALONADA (.anima)
     20. PREFERS-REDUCED-MOTION
     21. RESPONSIVE
     22. UTILIDADES
   ============================================================================ */


/* ============================================================================
   0. DECISIÓN DE ARQUITECTURA DE TEMAS
   ----------------------------------------------------------------------------
   *** IMPORTANTE — DIFIERE DE LA MAQUETA ORIGINAL ***

   En la maqueta aprobada el tema OSCURO vivía en :root y el CLARO sobrescribía
   en [data-theme="light"]. AQUÍ ESTÁ AL REVÉS, a propósito:

       :root                 -> paleta CLARA "Grafito Humo"   (predeterminada)
       [data-theme="dark"]   -> paleta OSCURA "Acero"         (opt-in)

   MOTIVO
   El ERP sintegrado arranca en CLARO por decisión de marca de PVM SAS. El tema
   se aplica con un pequeño script que escribe data-theme en <html>. Si ese
   script falla, el usuario tiene JavaScript desactivado, o el HTML se sirve sin
   el atributo (correos, impresiones, vistas exportadas, cachés parciales), el
   navegador debe caer en el tema CLARO —el predeterminado real del producto—
   y nunca en el oscuro. Poniendo el claro en :root, el "modo sin JS" es
   exactamente el modo por defecto del producto. La regresión visual pasa a ser
   imposible: no hay estado en el que se vea un tema que el cliente no aprobó
   como predeterminado.

   CONSECUENCIA PRÁCTICA
   Los estados invertidos del conmutador día/noche también se invirtieron: el
   estado "en reposo" del control es ahora el CLARO, y [data-theme="dark"] es
   el que mueve la perilla y cambia los iconos (ver sección 9.5).

   CONTRATO CON EL HTML
     <html lang="es" data-theme="light">   <- explícito, recomendado
     <html lang="es">                      <- también válido: cae en claro
     <html lang="es" data-theme="dark">    <- único caso que activa el oscuro
   ============================================================================ */


/* ============================================================================
   1. TOKENS — TEMA CLARO · "GRAFITO HUMO"   (PREDETERMINADO, sin JS)
      Gris medio CON CUERPO, no blanco: sala de máquinas de día.
      Aquí viven TODOS los tokens: color y no-color. El tema oscuro (sección 2)
      solo sobrescribe los de color, textura y sombra.
   ============================================================================ */
:root {

  /* Informa al navegador para que pinte controles nativos y barras acordes. */
  color-scheme: light;

  /* --- SUPERFICIES ------------------------------------------------------- */
  --bg-0: #e9eaec;          /* fondo de página: gris con cuerpo, no plantilla */
  --bg-1: #eff0f2;          /* app bar, panel lateral, superficies fijas      */
  --bg-2: #f7f8f9;          /* tarjetas y contenedores de contenido           */
  --bg-3: #ffffff;          /* superficie elevada: hover, campos, chips       */
  --bg-inset: #e0e2e5;      /* rebajes: buscador, huecos, micro-gráficas      */

  /* --- LÍNEAS Y REJILLA -------------------------------------------------- */
  --line-1: #d3d6da;        /* borde estándar de tarjeta / separador fuerte   */
  --line-2: #dfe1e4;        /* separador tenue dentro de un mismo bloque      */
  --line-3: #b9bec5;        /* borde marcado: foco de bloque, divisor duro    */
  --grid: rgba(22,24,27,.035);     /* rejilla técnica del fondo de página     */

  /* --- TEXTO ------------------------------------------------------------- */
  --ink-1: #16181b;         /* títulos y cifras                               */
  --ink-2: #4e545c;         /* descripciones y etiquetas                      */
  /* Metadatos: cabeceras de tabla, etiquetas, rótulos del panel lateral.
     Es el gris MÁS CLARO que cumple WCAG AA (4,5:1) sobre TODOS los fondos
     claros, incluido el más oscuro de ellos, --bg-inset #e0e2e5, donde da
     4,54:1. El valor anterior (#6b7178) se calibró solo contra --bg-2 y se
     quedaba en 3,80:1 sobre --bg-inset y 4,32:1 en las cabeceras de tabla,
     que usan --bg-1: por debajo del mínimo, y en texto de 9,5 px. */
  --ink-3: #5f656c;
  --ink-faint: #7c838c;     /* SOLO decorativo: numeración, marcas de agua    */
  --ink-invert: #ffffff;    /* texto sobre relleno de acento (AA · 4,5:1)     */

  /* --- ACENTO PRIMARIO · ÁMBAR QUEMADO ----------------------------------- */
  --acc: #c2560b;                       /* rellenos, bordes, indicadores      */
  --acc-ink: #a8480a;                   /* acento en TEXTO (contraste AA)     */
  --acc-copper: #8a3d06;                /* cobre: sombra del acento, degradé  */
  --acc-soft: rgba(194,86,11,.11);      /* relleno tenue / fondo de chip      */
  --acc-line: rgba(194,86,11,.38);      /* borde de acento                    */
  --acc-glow: rgba(194,86,11,.20);      /* halo de foco / hover               */

  /* --- ACENTO SECUNDARIO · ACERO ----------------------------------------- */
  --sec: #0f6f92;
  --sec-ink: #0d5e7c;
  --sec-soft: rgba(15,111,146,.10);
  --sec-line: rgba(15,111,146,.34);

  /* --- ESTADOS SEMÁNTICOS ------------------------------------------------ */
  --ok:   #15803d;  --ok-soft:   rgba(21,128,61,.10);
  --warn: #a35a06;  --warn-soft: rgba(163,90,6,.12);
  --dang: #b91c1c;  --dang-soft: rgba(185,28,28,.10);

  /* --- MICRO-TEXTURA "METAL MECANIZADO" (versión diurna) -----------------
     Rayado fino vertical (torneado) + brillo superior de chapa satinada.
     Se aplican como background-image sobre superficies fijas y tarjetas.     */
  --tex-brush: repeating-linear-gradient(
      90deg,
      rgba(22,24,27,.022) 0 1px,
      rgba(0,0,0,0) 1px 3px);
  --tex-sheen: linear-gradient(180deg,
      rgba(255,255,255,.85) 0,
      rgba(255,255,255,.28) 40%,
      rgba(255,255,255,0) 68%);
  --tex-edge: rgba(255,255,255,.9);     /* filo superior de 1px              */

  /* --- SOMBRAS (neutras y cortas: nada difuso en tema claro) ------------- */
  --sh-1: 0 1px 1px rgba(22,24,27,.06);
  --sh-2: 0 8px 18px rgba(22,24,27,.10), 0 2px 4px rgba(22,24,27,.07);
  --sh-inset: inset 0 1px 0 var(--tex-edge);
  --sh-focus: 0 0 0 3px var(--acc-glow);
  --sh-knob: 0 1px 2px rgba(22,24,27,.30), inset 0 1px 0 rgba(255,255,255,.34);

  /* --- TIPOGRAFÍA (con fallbacks con carácter, por si no carga la web font)
     display -> títulos, marca, nombres de módulo (condensada técnica)
     body    -> textos corridos e interfaz
     mono    -> cifras, etiquetas técnicas, metadatos                        */
  --f-display: 'Chakra Petch','Rajdhani','Oswald','Segoe UI Semibold',system-ui,sans-serif;
  --f-body:    'IBM Plex Sans','Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;
  --f-mono:    'IBM Plex Mono','SFMono-Regular',ui-monospace,Consolas,'Courier New',monospace;

  /* --- ESCALA DE ESPACIADO (base 4px) ------------------------------------ */
  --sp-1: 4px;   --sp-2: 8px;   --sp-3: 12px;  --sp-4: 16px;
  --sp-5: 20px;  --sp-6: 24px;  --sp-7: 32px;  --sp-8: 44px;  --sp-9: 64px;

  /* --- RADIOS (esquina contenida: pieza mecanizada, no burbuja) ----------- */
  --r-xs: 2px;  --r-sm: 4px;  --r-md: 6px;  --r-lg: 9px;  --r-pill: 999px;
  --bevel: 13px;            /* tamaño del bisel técnico de esquina (.bisel)  */

  /* --- TRANSICIONES ------------------------------------------------------ */
  --tr-fast: 130ms cubic-bezier(.22,.61,.36,1);
  --tr:      220ms cubic-bezier(.22,.61,.36,1);
  --tr-slow: 420ms cubic-bezier(.16,1,.3,1);
  --ease-out: cubic-bezier(.16,1,.3,1);

  /* --- LAYOUT ------------------------------------------------------------ */
  --nav-w: 252px;           /* ancho del panel lateral                       */
  --bar-h: 60px;            /* alto de la app bar fija                       */
  --maxw: 1560px;           /* ancho máximo del contenido                    */
}


/* ============================================================================
   2. TOKENS — TEMA OSCURO · "ACERO"    (opt-in: <html data-theme="dark">)
      Grafito profundo con matiz cálido. Sala de control nocturna.
      SOLO se sobrescriben color, textura y sombra: tipografía, espaciado,
      radios, transiciones y layout son COMUNES a ambos temas (sección 1).
   ============================================================================ */
[data-theme="dark"] {

  color-scheme: dark;

  /* --- SUPERFICIES ------------------------------------------------------- */
  --bg-0: #0e0f11;          /* fondo de página, el plano más profundo        */
  --bg-1: #16181b;          /* app bar, panel lateral, superficies fijas     */
  --bg-2: #1e2125;          /* tarjetas y contenedores de contenido          */
  --bg-3: #262a2f;          /* superficie elevada: hover, campos, chips      */
  --bg-inset: #121417;      /* rebajes: buscador, huecos, micro-gráficas     */

  /* --- LÍNEAS Y REJILLA -------------------------------------------------- */
  --line-1: #2b2f35;
  --line-2: #22262b;
  --line-3: #3a4047;
  --grid: rgba(255,255,255,.020);

  /* --- TEXTO ------------------------------------------------------------- */
  --ink-1: #e9ebee;
  --ink-2: #9ba2ab;
  --ink-3: #8a919a;         /* calibrado para cumplir AA sobre --bg-2        */
  --ink-faint: #6d757e;     /* SOLO decorativo                               */
  --ink-invert: #0e0f11;    /* texto sobre relleno de acento                 */

  /* --- ACENTO PRIMARIO · ÁMBAR-COBRE (metal al rojo) --------------------- */
  --acc: #f97316;
  --acc-ink: #fb923c;                   /* acento en TEXTO (contraste AA)    */
  --acc-copper: #b45309;
  --acc-soft: rgba(249,115,22,.14);
  --acc-line: rgba(249,115,22,.42);
  --acc-glow: rgba(249,115,22,.16);

  /* --- ACENTO SECUNDARIO · ACERO ----------------------------------------- */
  --sec: #38bdf8;
  --sec-ink: #7dd3fc;
  --sec-soft: rgba(56,189,248,.13);
  --sec-line: rgba(56,189,248,.38);

  /* --- ESTADOS SEMÁNTICOS ------------------------------------------------ */
  --ok:   #34d399;  --ok-soft:   rgba(52,211,153,.13);
  --warn: #fbbf24;  --warn-soft: rgba(251,191,36,.13);
  --dang: #f87171;  --dang-soft: rgba(248,113,113,.13);

  /* --- MICRO-TEXTURA "METAL MECANIZADO" (versión nocturna) --------------- */
  --tex-brush: repeating-linear-gradient(
      90deg,
      rgba(255,255,255,.016) 0 1px,
      rgba(0,0,0,0) 1px 3px);
  --tex-sheen: linear-gradient(180deg,
      rgba(255,255,255,.055) 0,
      rgba(255,255,255,.012) 38%,
      rgba(0,0,0,0) 62%);
  --tex-edge: rgba(255,255,255,.07);

  /* --- SOMBRAS (más largas y contrastadas: hay menos luz ambiente) ------- */
  --sh-1: 0 1px 2px rgba(0,0,0,.45);
  --sh-2: 0 10px 26px rgba(0,0,0,.46), 0 2px 6px rgba(0,0,0,.34);
  --sh-inset: inset 0 1px 0 var(--tex-edge);
  --sh-focus: 0 0 0 3px var(--acc-glow);
  --sh-knob: 0 1px 3px rgba(0,0,0,.42), inset 0 1px 0 rgba(255,255,255,.26);
}


/* ============================================================================
   ORDEN DE LAS CAPAS DE CASCADA        (declararlo ANTES de usarlas)
   ----------------------------------------------------------------------------
   De menor a mayor prioridad:

       pvm-reset   <   pvm-componentes   <   (todo lo que va SIN capa)

   · pvm-reset ......... normalización del navegador (sección 3).
   · pvm-componentes ... piezas con nombres genéricos: .btn .card .badge .chip
                         .kpi .tabla (secciones 12-18 y 21).
   · sin capa .......... tokens, foco/accesibilidad, layout, utilidades…
                         y, sobre todo, el <style> propio de CADA MÓDULO.

   La regla de oro de @layer: lo que está SIN capa gana SIEMPRE a lo que está en
   una capa, sin importar la especificidad ni el orden de carga. Por eso cada
   módulo del ERP manda sobre estas reglas base aunque theme.css se cargue
   después que él (que es justo lo que ocurre en las pantallas que reciben la
   hoja desde navbar.php, ya dentro del <body>).

   Sigue siendo por PROPIEDAD: si un módulo solo cambia el color de .btn, la
   altura y el radio los sigue poniendo esta hoja.
   ============================================================================ */
@layer pvm-reset, pvm-componentes;


/* ============================================================================
   3. RESET Y BASE
   ----------------------------------------------------------------------------
   VA EN LA CAPA "pvm-reset", QUE ES LA MÁS DÉBIL DE TODAS.
   El orden declarado arriba es:  pvm-reset  <  pvm-componentes  <  sin capa.

   Es imprescindible que el reset esté en una capa PROPIA y anterior. Las capas
   mandan sobre la especificidad: si el reset se quedara fuera de toda capa,
   reglas tan genéricas como "* { padding: 0 }" o
   "button { background: none; border: none }" le ganarían a .btn (que sí está
   en capa) pese a tener menos especificidad, y TODOS los botones del ERP se
   quedarían planos y sin relleno. Ocurrió al introducir las capas y así se
   corrigió.
   ============================================================================ */
@layer pvm-reset {

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

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

body {
  font-family: var(--f-body);
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-1);
  background-color: var(--bg-0);
  /* Rejilla técnica de fondo: plano de taller, muy tenue. */
  background-image:
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 36px 36px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
  overflow-x: hidden;
}

/* Elementos que heredan en lugar de imponer su propio estilo del navegador. */
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
a { color: inherit; text-decoration: none; }
input, select, textarea { font: inherit; color: inherit; }
img, svg, video, canvas { max-width: 100%; }

::selection { background: var(--acc-soft); color: var(--acc-ink); }

/* --- Barra de desplazamiento a tono del tema ---------------------------- */
* { scrollbar-width: thin; scrollbar-color: var(--line-3) transparent; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--line-3);
  border: 3px solid var(--bg-0);
  border-radius: var(--r-pill);
}
::-webkit-scrollbar-thumb:hover { background: var(--ink-faint); }

} /* ── fin de @layer pvm-reset ────────────────────────────────────────────── */


/* ============================================================================
   4. TRANSICIÓN DE TEMA
      La clase .cambiando-tema la añade el JS al <html> SOLO durante el toggle,
      para que la conmutación sea suave sin ensuciar los hovers del resto del
      tiempo (si estas transiciones fueran permanentes, cada hover arrastraría
      420ms de retardo en toda la página).
      Uso: html.classList.add('cambiando-tema'); ... quitar a los ~460ms.
   ============================================================================ */
html.cambiando-tema,
html.cambiando-tema *,
html.cambiando-tema *::before,
html.cambiando-tema *::after {
  transition: background-color var(--tr-slow),
              border-color var(--tr-slow),
              color var(--tr-slow),
              fill var(--tr-slow),
              stroke var(--tr-slow),
              box-shadow var(--tr-slow),
              stop-color var(--tr-slow) !important;
  transition-delay: 0s !important;
}


/* ============================================================================
   5. ACCESIBILIDAD Y FOCO
      Regla no negociable: todo lo enfocable muestra un anillo visible. Se usa
      el acento SECUNDARIO (acero) para que el foco no se confunda con el
      estado "activo/seleccionado", que usa el acento primario.
   ============================================================================ */
:where(a, button, input, select, textarea, summary, [tabindex]):focus { outline: none; }

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--sec);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

/* Texto solo para lectores de pantalla. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Enlace "saltar al contenido": oculto hasta recibir foco por teclado. */
.skip-link {
  position: absolute; top: -60px; left: var(--sp-4);
  z-index: 200;
  padding: var(--sp-2) var(--sp-4);
  font-family: var(--f-mono); font-size: 12px; letter-spacing: .08em;
  color: var(--ink-invert);
  background: var(--acc);
  border-radius: var(--r-sm);
  transition: top var(--tr);
}
.skip-link:focus-visible { top: var(--sp-2); }

/* Estado deshabilitado, transversal a todos los componentes. */
[disabled], .is-disabled, [aria-disabled="true"] {
  opacity: .5;
  pointer-events: none;
  cursor: not-allowed;
}


/* ============================================================================
   6. SISTEMA DE ICONOS
      Set propio dibujado sobre rejilla de 24. Trazo 1.6, remates rectos,
      uniones en inglete. MOTIVO DE FIRMA: "trazo seccionado" — en cada glifo
      una línea lleva un corte técnico intencional, como en un plano de
      despiece. Los iconos heredan el color del contenedor (currentColor).
   ============================================================================ */
.ico {
  width: 24px; height: 24px; flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: butt;
  stroke-linejoin: miter;
  stroke-miterlimit: 6;
  vector-effect: non-scaling-stroke;
}
.ico--sm { width: 18px; height: 18px; stroke-width: 1.75; }
.ico--xs { width: 15px; height: 15px; stroke-width: 1.8; }
.ico--lg { width: 26px; height: 26px; }


/* ============================================================================
   7. BISEL TÉCNICO DE ESQUINA (.bisel)
      Motivo compartido con los iconos: corta la esquina superior derecha y
      dibuja el filo con la línea del tema. Se aplica a tarjetas y paneles.
      OJO: el elemento con .bisel NO debe llevar overflow:hidden, o recortaría
      el propio bisel.
   ============================================================================ */
.bisel { position: relative; }
.bisel::after {
  content: '';
  position: absolute;
  top: -1px; right: -1px;
  width: var(--bevel); height: var(--bevel);
  pointer-events: none;
  background: linear-gradient(45deg,
      rgba(0,0,0,0) 0 49.2%,
      var(--line-1) 49.2% 51.2%,
      var(--bg-0) 51.2% 100%);
}


/* ============================================================================
   8. ESQUELETO DE LAYOUT
      App bar fija arriba (ocupa las dos columnas) + navegación lateral pegajosa
      + área de contenido. Las dos columnas usan minmax(0,1fr) para que ningún
      contenido ancho (tablas, gráficas) provoque scroll horizontal.
   ============================================================================ */
.app {
  display: grid;
  grid-template-columns: var(--nav-w) minmax(0, 1fr);
  grid-template-rows: var(--bar-h) minmax(0, 1fr);
  min-height: 100vh;
}

.main { min-width: 0; padding: var(--sp-7) var(--sp-7) var(--sp-9); }
.wrap { max-width: var(--maxw); margin: 0 auto; }


/* ============================================================================
   9. APP BAR
   ============================================================================ */
.appbar {
  grid-column: 1 / -1;
  position: sticky; top: 0; z-index: 60;
  height: var(--bar-h);
  display: flex; align-items: center; gap: var(--sp-5);
  padding: 0 var(--sp-5);
  background-color: var(--bg-1);
  background-image: var(--tex-brush), var(--tex-sheen);
  border-bottom: 1px solid var(--line-1);
  box-shadow: var(--sh-1);
}

/* ---------------------------------------------------------------------------
   9.1 MARCA
   --------------------------------------------------------------------------- */
.brand { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.brand__mark { width: 30px; height: 30px; flex: none; color: var(--acc); }
.brand__mark .nut  { stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linejoin: miter; }
.brand__mark .core { stroke: var(--ink-2);  fill: none; stroke-width: 1.5; }
.brand__txt { display: flex; flex-direction: column; line-height: 1.05; min-width: 0; }
.brand__name {
  font-family: var(--f-display);
  font-weight: 700; font-size: 15px; letter-spacing: .10em;
  text-transform: uppercase; color: var(--ink-1); white-space: nowrap;
}
.brand__sub {
  font-family: var(--f-mono);
  font-size: 10.5px; letter-spacing: .16em;
  color: var(--acc-ink); white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   9.2 BUSCADOR GLOBAL
   Campo rebajado (inset) que se "enciende" al recibir el foco dentro.
   --------------------------------------------------------------------------- */
.search {
  position: relative;
  flex: 1 1 auto; max-width: 460px;
  display: flex; align-items: center; gap: var(--sp-2);
  height: 36px; padding: 0 var(--sp-2) 0 var(--sp-3);
  background: var(--bg-inset);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  transition: border-color var(--tr-fast), box-shadow var(--tr-fast), background-color var(--tr-fast);
}
.search:focus-within {
  border-color: var(--acc-line);
  box-shadow: var(--sh-focus);
  background: var(--bg-3);
}
.search__ico { color: var(--ink-3); flex: none; }
.search:focus-within .search__ico { color: var(--acc-ink); }
.search input {
  flex: 1; min-width: 0; height: 100%;
  background: none; border: none; outline: none;
  font-size: 13px; color: var(--ink-1);
}
.search input::placeholder { color: var(--ink-3); }

/* Tecla / atajo representado como pieza física (borde inferior de 2px). */
.kbd {
  display: inline-flex; align-items: center; gap: 2px;
  font-family: var(--f-mono); font-size: 10px; letter-spacing: .06em;
  color: var(--ink-3);
  padding: 3px 6px;
  border: 1px solid var(--line-1);
  border-bottom-width: 2px;
  border-radius: var(--r-xs);
  background: var(--bg-2);
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   9.3 ACCIONES DE LA BARRA
   --------------------------------------------------------------------------- */
.bar-actions { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; }
.bar-div { width: 1px; height: 26px; background: var(--line-1); margin: 0 var(--sp-1); }

/* ---------------------------------------------------------------------------
   9.4 USUARIO
   --------------------------------------------------------------------------- */
.user { display: flex; align-items: center; gap: var(--sp-3); padding-left: var(--sp-1); }
.user__av {
  width: 34px; height: 34px; flex: none;
  display: grid; place-items: center;
  font-family: var(--f-display); font-weight: 700; font-size: 12.5px; letter-spacing: .06em;
  color: var(--acc-ink);
  background: var(--acc-soft);
  border: 1px solid var(--acc-line);
  border-radius: var(--r-sm);
}
.user__txt { display: flex; flex-direction: column; line-height: 1.2; }
.user__name { font-size: 12.5px; font-weight: 600; color: var(--ink-1); white-space: nowrap; }
.user__role {
  font-family: var(--f-mono); font-size: 10px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3); white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   9.5 CONMUTADOR DÍA / NOCHE
   ESTADOS INVERTIDOS RESPECTO A LA MAQUETA (ver sección 0): el estado en
   reposo del control representa el tema CLARO, que es el predeterminado.
   La perilla arranca a la DERECHA (sol activo) y [data-theme="dark"] la
   devuelve a la izquierda encendiendo la luna.
   Marcado esperado: <button class="themebtn" role="switch" aria-checked>
                       <span class="themebtn__knob"></span>
                       <span class="themebtn__ico themebtn__ico--luna">…</span>
                       <span class="themebtn__ico themebtn__ico--sol">…</span>
                     </button>
   --------------------------------------------------------------------------- */
.themebtn {
  position: relative;
  width: 62px; height: 32px;
  display: flex; align-items: center;
  padding: 0 4px;
  background: var(--bg-inset);
  border: 1px solid var(--line-1);
  border-radius: var(--r-pill);
  transition: border-color var(--tr), background-color var(--tr);
}
.themebtn:hover { border-color: var(--line-3); }

.themebtn__knob {
  position: absolute; top: 3px; left: 3px;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: linear-gradient(160deg, var(--acc) 0%, var(--acc-copper) 100%);
  box-shadow: var(--sh-knob);
  /* Reposo = tema CLARO -> perilla a la derecha, sobre el sol. */
  transform: translateX(30px);
  transition: transform var(--tr-slow), background var(--tr);
}
[data-theme="dark"] .themebtn__knob { transform: translateX(0); }

.themebtn__ico {
  position: relative; z-index: 1;
  width: 24px; height: 24px;
  display: grid; place-items: center;
  transition: color var(--tr), opacity var(--tr), transform var(--tr-slow);
}
.themebtn__ico .ico { width: 15px; height: 15px; stroke-width: 1.8; }

/* Reposo (tema claro): sol encendido sobre la perilla, luna apagada. */
.themebtn__ico--luna { color: var(--ink-3); opacity: .8; transform: rotate(20deg); }
.themebtn__ico--sol  { color: var(--ink-invert); opacity: 1; transform: rotate(0deg); margin-left: 6px; }

/* Tema oscuro activo: se invierte. */
[data-theme="dark"] .themebtn__ico--luna { color: var(--ink-invert); opacity: 1; transform: rotate(0deg); }
[data-theme="dark"] .themebtn__ico--sol  { color: var(--ink-3); opacity: .8; transform: rotate(-25deg); }


/* ============================================================================
   10. NAVEGACIÓN LATERAL
   ============================================================================ */
.nav {
  position: sticky; top: var(--bar-h);
  height: calc(100vh - var(--bar-h));
  overflow-y: auto;
  padding: var(--sp-5) var(--sp-3) var(--sp-6);
  background-color: var(--bg-1);
  background-image: var(--tex-brush);
  border-right: 1px solid var(--line-1);
  display: flex; flex-direction: column; gap: 2px;
}

/* Etiqueta de sección con filete que rellena el espacio sobrante. */
.nav__label {
  font-family: var(--f-mono); font-size: 9.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-3);
  padding: 0 var(--sp-3); margin-bottom: var(--sp-2);
  display: flex; align-items: center; gap: var(--sp-2);
}
.nav__label::after { content: ''; flex: 1; height: 1px; background: var(--line-2); }

.nav__item {
  position: relative;
  display: flex; align-items: center; gap: var(--sp-3);
  width: 100%;
  padding: 9px var(--sp-3);
  border-radius: var(--r-sm);
  color: var(--ink-2);
  text-align: left;
  transition: color var(--tr-fast), background-color var(--tr-fast);
}
.nav__item .ico { color: var(--ink-3); transition: color var(--tr-fast); }
.nav__item span { font-size: 13px; font-weight: 500; flex: 1; min-width: 0; }
.nav__item .n { font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-faint); }

/* Marcador vertical de acento: crece desde el centro al activarse. */
.nav__item::before {
  content: ''; position: absolute; left: 0; top: 50%;
  width: 2px; height: 0; transform: translateY(-50%);
  background: var(--acc);
  transition: height var(--tr);
}
.nav__item:hover { color: var(--ink-1); background: var(--bg-2); }
.nav__item:hover .ico { color: var(--ink-2); }

.nav__item.is-active {
  color: var(--ink-1);
  background: var(--bg-2);
  box-shadow: inset 0 0 0 1px var(--line-1);
}
.nav__item.is-active::before { height: 62%; }
.nav__item.is-active .ico { color: var(--acc-ink); }
.nav__item.is-active .n   { color: var(--acc-ink); }

.nav__sep { height: 1px; background: var(--line-2); margin: var(--sp-3); }

/* --- Bloque de estado de planta (pie del panel lateral) ------------------
   Densidad informativa propia de un ERP: lecturas rápidas al final del menú. */
.plant {
  margin-top: auto;
  padding: var(--sp-3);
  background: var(--bg-2);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
}
.plant__t {
  font-family: var(--f-mono); font-size: 9.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: var(--sp-2);
}
.plant__row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-2); padding: 3px 0;
  font-size: 11.5px; color: var(--ink-2);
}
.plant__row b {
  font-family: var(--f-mono); font-weight: 500; color: var(--ink-1); font-size: 11.5px;
}


/* ============================================================================
   11. ENCABEZADO DE PÁGINA
       Patrón: eyebrow (rótulo técnico) + título + descripción, con metadatos
       alineados a la derecha. Se usa en TODAS las pantallas del ERP.
   ============================================================================ */
.hero {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--sp-6); flex-wrap: wrap;
  padding-bottom: var(--sp-5);
  margin-bottom: var(--sp-6);
  border-bottom: 1px solid var(--line-1);
}
.eyebrow {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-3);
  margin-bottom: var(--sp-3);
}
.eyebrow::before { content: ''; width: 22px; height: 2px; background: var(--acc); }

.hero h1 {
  font-family: var(--f-display);
  font-size: clamp(22px, 2.4vw, 30px);
  font-weight: 600; letter-spacing: .005em; line-height: 1.15;
  color: var(--ink-1);
}
/* <em> dentro del título = palabra destacada en acento, sin cursiva. */
.hero h1 em { font-style: normal; color: var(--acc-ink); }
.hero p { margin-top: var(--sp-2); font-size: 13.5px; color: var(--ink-2); max-width: 62ch; }

.hero__meta { display: flex; gap: var(--sp-6); flex-wrap: wrap; }
.metaitem { display: flex; flex-direction: column; gap: 3px; }
.metaitem dt {
  font-family: var(--f-mono); font-size: 9.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-3);
}
.metaitem dd {
  font-family: var(--f-mono); font-size: 13px; font-weight: 500; color: var(--ink-1);
  display: flex; align-items: center; gap: var(--sp-2);
}


/* ============================================================================
   CAPA DE COMPONENTES  ·  @layer pvm-componentes      (secciones 12 a 18)
   ----------------------------------------------------------------------------
   POR QUÉ EXISTE ESTA CAPA
     Las piezas de aquí abajo usan nombres de clase MUY comunes: .btn, .card,
     .badge, .chip, .kpi, .tabla. Cada módulo del ERP trae su propio <style> con
     esos mismos nombres, escritos años antes que esta hoja.

     Sin capas, quien gana un empate de especificidad depende del ORDEN DE
     CARGA, y ese orden no es el mismo en todas las pantallas: las páginas ya
     migradas piden theme.css en su <head> (y entonces el módulo gana, que es lo
     correcto), pero las que aún no lo están lo reciben desde navbar.php, que se
     incluye YA DENTRO DEL <body>. Ahí theme.css cargaba DESPUÉS del <style> del
     módulo y le pisaba los botones y las tarjetas: un módulo intacto se veía
     roto sin que nadie hubiera tocado su código.

   QUÉ HACE @layer
     Lo que está dentro de una capa SIEMPRE pierde frente a lo que está fuera de
     toda capa, sin importar el orden ni la especificidad. Como el <style> de
     cada módulo está fuera de capas, el módulo manda SIEMPRE sobre estas reglas
     base. Y sigue siendo por PROPIEDAD: si un módulo solo redefine el color de
     .btn, hereda de aquí la altura, el radio y el resto.

   CONSECUENCIA PRÁCTICA
     Ya no hace falta el ritual de "neutralizar" .btn/.card/.badge en cada
     módulo que se migra. Los parches de neutralización que ya existen quedan
     inofensivos (siguen ganando, solo que ahora ganarían igual sin estar).

   COMPATIBILIDAD
     Capas de cascada: Chrome 99+, Firefox 97+, Safari 15.4+ (todos de 2022).
     Un navegador anterior ignora el bloque entero y las pantallas se verían sin
     estilo de componentes; si alguna vez hay que dar soporte a uno así, se
     quitan las dos líneas @layer y se vuelve al comportamiento anterior.

   FUERA DE LA CAPA A PROPÓSITO
     · Tokens (secciones 1-2), reset, foco y accesibilidad: deben aplicarse
       siempre.
     · Sección 20 (prefers-reduced-motion): tiene que poder anular las
       animaciones de CUALQUIER módulo, así que no puede ir en una capa.
     · Sección 22 (utilidades): existen justamente para imponerse.
   ============================================================================ */
@layer pvm-componentes {

/* ============================================================================
   12. BOTONES
       .btn        botón de texto, variantes por modificador
       .iconbtn    botón cuadrado de solo icono (barra de herramientas)
       Todos comparten altura de 34/36px para alinear en filas de acciones.
   ============================================================================ */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--sp-2);
  height: 34px; padding: 0 var(--sp-4);
  font-family: var(--f-body); font-size: 12.5px; font-weight: 600;
  letter-spacing: .02em; white-space: nowrap;
  color: var(--ink-1);
  background-color: var(--bg-2);
  background-image: var(--tex-sheen);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  box-shadow: var(--sh-1);
  cursor: pointer;
  transition: color var(--tr-fast), background-color var(--tr-fast),
              border-color var(--tr-fast), box-shadow var(--tr-fast),
              transform var(--tr-fast);
}
.btn:hover { background-color: var(--bg-3); border-color: var(--line-3); }
.btn:active { transform: translateY(1px); box-shadow: none; }
.btn .ico { width: 16px; height: 16px; stroke-width: 1.75; }

/* Variante primaria: acción principal de la pantalla. Una por vista. */
.btn--acc {
  color: var(--ink-invert);
  background-color: var(--acc);
  background-image: linear-gradient(160deg, var(--acc) 0%, var(--acc-copper) 140%);
  border-color: var(--acc);
}
.btn--acc:hover { border-color: var(--acc-copper); filter: brightness(1.06); }

/* Variante secundaria "acero": acciones de navegación o exportación. */
.btn--sec {
  color: var(--sec-ink);
  background-color: var(--sec-soft);
  background-image: none;
  border-color: var(--sec-line);
}
.btn--sec:hover { border-color: var(--sec); }

/* Variante destructiva: eliminar, anular, rechazar. */
.btn--dang {
  color: var(--dang);
  background-color: var(--dang-soft);
  background-image: none;
  border-color: var(--dang);
}
.btn--dang:hover { color: var(--ink-invert); background-color: var(--dang); }

/* Variante fantasma: acciones terciarias, sin peso visual. */
.btn--ghost {
  color: var(--ink-2);
  background-color: transparent;
  background-image: none;
  border-color: transparent;
  box-shadow: none;
}
.btn--ghost:hover { color: var(--ink-1); background-color: var(--bg-3); border-color: var(--line-1); }

/* Tamaños alternativos. */
.btn--sm { height: 28px; padding: 0 var(--sp-3); font-size: 11.5px; }
.btn--lg { height: 40px; padding: 0 var(--sp-5); font-size: 13.5px; }
.btn--block { width: 100%; }

/* --- Botón de solo icono ------------------------------------------------- */
.iconbtn {
  position: relative;
  width: 36px; height: 36px;
  display: grid; place-items: center;
  color: var(--ink-2);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  transition: color var(--tr-fast), background-color var(--tr-fast), border-color var(--tr-fast);
}
.iconbtn:hover { color: var(--ink-1); background: var(--bg-3); border-color: var(--line-1); }
.iconbtn.is-active { color: var(--acc-ink); background: var(--acc-soft); border-color: var(--acc-line); }

/* Contador flotante (notificaciones, pendientes). El borde del color de la
   barra recorta el badge contra el icono y lo hace legible. */
.iconbtn__badge {
  position: absolute; top: 4px; right: 4px;
  min-width: 16px; height: 16px; padding: 0 3px;
  display: grid; place-items: center;
  font-family: var(--f-mono); font-size: 9.5px; font-weight: 600; line-height: 1;
  color: var(--ink-invert); background: var(--acc);
  border-radius: var(--r-pill);
  border: 2px solid var(--bg-1);
}


/* ============================================================================
   13. CHIPS, BADGES, TENDENCIAS Y PUNTOS DE ESTADO
       Piezas pequeñas de etiquetado. Todas usan la pareja color/color-soft del
       token semántico correspondiente, así el contraste queda garantizado en
       ambos temas sin escribir un solo color literal.
   ============================================================================ */

/* --- Chip: etiqueta con borde, puede ser interactiva (filtros) ----------- */
.chip {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  height: 24px; padding: 0 var(--sp-2);
  font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .08em;
  text-transform: uppercase; white-space: nowrap;
  color: var(--ink-2);
  background: var(--bg-3);
  border: 1px solid var(--line-1);
  border-radius: var(--r-xs);
  transition: color var(--tr-fast), background-color var(--tr-fast), border-color var(--tr-fast);
}
.chip .ico { width: 13px; height: 13px; stroke-width: 1.8; }
button.chip:hover, a.chip:hover { color: var(--ink-1); border-color: var(--line-3); }
.chip.is-active { color: var(--acc-ink); background: var(--acc-soft); border-color: var(--acc-line); }

/* Variantes semánticas del chip. */
.chip--acc  { color: var(--acc-ink); background: var(--acc-soft);  border-color: var(--acc-line); }
.chip--sec  { color: var(--sec-ink); background: var(--sec-soft);  border-color: var(--sec-line); }
.chip--ok   { color: var(--ok);      background: var(--ok-soft);   border-color: var(--ok); }
.chip--warn { color: var(--warn);    background: var(--warn-soft); border-color: var(--warn); }
.chip--dang { color: var(--dang);    background: var(--dang-soft); border-color: var(--dang); }

/* --- Badge: etiqueta compacta sin borde, para estados dentro de tablas --- */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 7px;
  font-family: var(--f-mono); font-size: 10.5px; font-weight: 500; letter-spacing: .06em;
  line-height: 1.5; white-space: nowrap;
  color: var(--ink-2);
  background: var(--bg-3);
  border-radius: var(--r-xs);
}
.badge--acc  { color: var(--acc-ink); background: var(--acc-soft); }
.badge--sec  { color: var(--sec-ink); background: var(--sec-soft); }
.badge--ok   { color: var(--ok);      background: var(--ok-soft); }
.badge--warn { color: var(--warn);    background: var(--warn-soft); }
.badge--dang { color: var(--dang);    background: var(--dang-soft); }

/* --- Numeración destacada (usada por los grupos y por listados) ---------- */
.num {
  font-family: var(--f-mono); font-size: 11px; font-weight: 600; letter-spacing: .06em;
  color: var(--acc-ink);
  padding: 4px 8px;
  background: var(--acc-soft);
  border: 1px solid var(--acc-line);
  border-radius: var(--r-xs);
  flex: none;
}

/* --- Tendencia: variación de un indicador (sube / alerta / estable) ------ */
.trend {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--f-mono); font-size: 11.5px; font-weight: 500;
  padding: 3px 7px;
  border-radius: var(--r-xs);
  white-space: nowrap;
}
.trend--up   { color: var(--ok);      background: var(--ok-soft); }
.trend--down { color: var(--dang);    background: var(--dang-soft); }
.trend--warn { color: var(--warn);    background: var(--warn-soft); }
.trend--flat { color: var(--sec-ink); background: var(--sec-soft); }

/* --- Punto de estado: semáforo mínimo con halo del mismo color ----------- */
.dot {
  width: 6px; height: 6px; border-radius: 50%; flex: none;
  background: var(--ok); box-shadow: 0 0 0 3px var(--ok-soft);
}
.dot--warn { background: var(--warn); box-shadow: 0 0 0 3px var(--warn-soft); }
.dot--dang { background: var(--dang); box-shadow: 0 0 0 3px var(--dang-soft); }
.dot--off  { background: var(--ink-faint); box-shadow: 0 0 0 3px var(--bg-3); }


/* ============================================================================
   14. TARJETA GENÉRICA (.card)
       Contenedor base de contenido. Todo panel del ERP (formulario, listado,
       gráfica, ficha) debe apoyarse en esta pieza para mantener la misma
       superficie, borde, brillo y sombra.
       Combinable con .bisel para el filo técnico de esquina.
   ============================================================================ */
.card {
  position: relative;
  background-color: var(--bg-2);
  background-image: var(--tex-sheen);
  border: 1px solid var(--line-1);
  border-radius: var(--r-md);
  box-shadow: var(--sh-1);
}
.card__head {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line-2);
}
.card__t {
  font-family: var(--f-display);
  font-size: 13px; font-weight: 600; letter-spacing: .10em;
  text-transform: uppercase; color: var(--ink-1);
}
.card__d { font-size: 11.5px; color: var(--ink-3); }
/* Empuja las acciones del encabezado al extremo derecho. */
.card__actions { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }
.card__body { padding: var(--sp-4); }
.card__foot {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--line-2);
  font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .08em;
  color: var(--ink-3);
}
/* Variante rebajada: bloques secundarios dentro de otra tarjeta. */
.card--inset {
  background-color: var(--bg-inset);
  background-image: none;
  box-shadow: none;
}
/* Variante interactiva: la tarjeta entera es un enlace. */
.card--link { transition: border-color var(--tr), box-shadow var(--tr), transform var(--tr); }
.card--link:hover,
.card--link:focus-visible { border-color: var(--acc-line); box-shadow: var(--sh-2); transform: translateY(-2px); }


/* ============================================================================
   15. KPIs Y MICRO-GRÁFICAS
       Tarjeta de indicador con filo de color superior, cifra en monoespaciada
       y una micro-visualización SVG. El color del KPI se inyecta por instancia
       con la variable --kpi-c (ej. style="--kpi-c: var(--ok)"). Si no se
       define, cae en el acento primario.
   ============================================================================ */
.kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(248px, 1fr));
  gap: var(--sp-4);
  margin-bottom: var(--sp-8);
}

.kpi {
  position: relative;
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
  background-color: var(--bg-2);
  background-image: var(--tex-sheen);
  border: 1px solid var(--line-1);
  border-radius: var(--r-md);
  box-shadow: var(--sh-1);
  transition: border-color var(--tr), box-shadow var(--tr), transform var(--tr);
}
/* Filo de color superior: identifica el KPI sin gritar.
   No se usa overflow:hidden en la tarjeta para no recortar el bisel. */
.kpi::before {
  content: ''; position: absolute;
  top: -1px; left: -1px; right: -1px; height: 2px;
  background: var(--kpi-c, var(--acc));
  border-radius: var(--r-md) var(--r-md) 0 0;
  opacity: .9;
}
.kpi:hover { border-color: var(--line-3); box-shadow: var(--sh-2); transform: translateY(-2px); }

.kpi__top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3); }
.kpi__label {
  font-family: var(--f-mono); font-size: 10px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-3); line-height: 1.4;
}
.kpi__ico {
  width: 30px; height: 30px; flex: none;
  display: grid; place-items: center;
  color: var(--kpi-c, var(--acc));
  background: var(--bg-inset);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
}
.kpi__ico .ico { width: 17px; height: 17px; stroke-width: 1.75; }

.kpi__val {
  font-family: var(--f-mono);
  font-size: clamp(26px, 2.6vw, 32px);
  font-weight: 600; letter-spacing: -.02em; line-height: 1;
  color: var(--ink-1);
  display: flex; align-items: baseline; gap: 4px;
}
.kpi__val .u { font-size: 15px; font-weight: 400; color: var(--ink-3); letter-spacing: 0; }

.kpi__foot { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--sp-3); }
.kpi__note { font-size: 11px; color: var(--ink-3); text-align: right; line-height: 1.35; }

/* ---------------------------------------------------------------------------
   15.1 MICRO-VISUALIZACIONES (.viz)
   SVG en línea. Clases esperadas dentro del SVG:
     .linea  polilínea del dato        .area  relleno bajo la línea
     .marca  punto del último valor    .barra columna
     .base   línea de referencia
   --------------------------------------------------------------------------- */
.viz { width: 100%; height: 38px; display: block; }
.viz .linea {
  fill: none; stroke: var(--kpi-c, var(--acc)); stroke-width: 1.6;
  stroke-linejoin: round; stroke-linecap: butt; vector-effect: non-scaling-stroke;
}
.viz .area      { fill: var(--kpi-c, var(--acc)); opacity: .13; stroke: none; }
.viz .marca     { fill: var(--bg-2); stroke: var(--kpi-c, var(--acc)); stroke-width: 1.6; }
.viz .barra     { fill: var(--kpi-c, var(--acc)); opacity: .30; }
.viz .barra--on { opacity: .95; }
.viz .base      { stroke: var(--line-1); stroke-width: 1; }

/* ---------------------------------------------------------------------------
   15.2 ANIMACIÓN DE LAS GRÁFICAS ("previsualización" del dato)
   La línea se DIBUJA sola, el área crece desde la base y la marca final
   aparece al terminar el trazo. Da sensación de dato en vivo, no estático.
   Se dispara cuando el JS añade la clase .viz--go (al entrar en pantalla).
   Estado inicial: oculto. Si el JS no corre, ver nota en la sección 20.
   --------------------------------------------------------------------------- */
.viz .linea {
  /* 400 supera la longitud real de cualquiera de estas polilíneas, así que
     sirve como valor genérico para ocultar el trazo antes de animarlo. */
  stroke-dasharray: 400;
  stroke-dashoffset: 400;
}
.viz .area  { opacity: 0; transform: scaleY(.35); transform-origin: bottom; }
.viz .marca { opacity: 0; transform: scale(.4); transform-origin: center; transform-box: fill-box; }

.viz--go .linea { animation: trazar      1.15s cubic-bezier(.32,.72,.32,1) forwards; }
.viz--go .area  { animation: crecer-area  .85s cubic-bezier(.32,.72,.32,1) .12s forwards; }
.viz--go .marca { animation: marcar       .45s cubic-bezier(.34,1.56,.64,1) .95s forwards; }
.viz--go .barra { animation: subir-barra    .5s cubic-bezier(.32,.72,.32,1) backwards; }

/* Al pasar el mouse sobre el KPI la gráfica se "refresca": la marca late y el
   área se intensifica. Refuerza la lectura del indicador sin distraer. */
.kpi:hover .viz .area  { opacity: .22; }
.kpi:hover .viz .marca { animation: latir 1.1s ease-in-out infinite; }
.kpi:hover .viz .linea { stroke-width: 2; }
.viz .area, .viz .linea { transition: opacity var(--tr), stroke-width var(--tr); }


/* ============================================================================
   16. GRUPOS DE MÓDULOS Y TARJETAS DE MÓDULO
       Patrón del tablero principal: secciones numeradas con rejilla de accesos.
   ============================================================================ */
.grupo { margin-bottom: var(--sp-8); scroll-margin-top: calc(var(--bar-h) + 16px); }

.grupo__head { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-4); }
.grupo__num {
  font-family: var(--f-mono); font-size: 11px; font-weight: 600; letter-spacing: .06em;
  color: var(--acc-ink);
  padding: 4px 8px;
  background: var(--acc-soft);
  border: 1px solid var(--acc-line);
  border-radius: var(--r-xs);
  flex: none;
}
.grupo__titles { min-width: 0; }
.grupo__t {
  font-family: var(--f-display);
  font-size: 15px; font-weight: 600; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink-1); line-height: 1.2;
}
.grupo__d { font-size: 12px; color: var(--ink-3); margin-top: 1px; }
.grupo__rule { flex: 1; height: 1px; background: var(--line-1); min-width: 20px; }
.grupo__count {
  font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .1em;
  color: var(--ink-3); flex: none;
}

/* --- Rejilla de tarjetas ------------------------------------------------- */
.mods {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(264px, 1fr));
  gap: var(--sp-3);
}

/* --- Tarjeta de módulo ---------------------------------------------------
   Al soltar el mouse la tarjeta vuelve MÁS LENTO que al entrar: se percibe
   como un material con peso, no como un parpadeo. Por eso hay dos bloques de
   transition (reposo y hover) con curvas distintas.
   --------------------------------------------------------------------------- */
.mod {
  position: relative;
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-4);
  background-color: var(--bg-2);
  background-image: var(--tex-sheen);
  border: 1px solid var(--line-1);
  border-radius: var(--r-md);
  text-align: left;
  transition:
    transform .34s cubic-bezier(.22,.68,.36,1),
    box-shadow .34s cubic-bezier(.22,.68,.36,1),
    border-color .2s ease,
    background-color .2s ease;
}
/* Marcador lateral de acento, aparece al enfocar o pasar por encima. */
.mod::before {
  content: ''; position: absolute; left: -1px; top: 12px; bottom: 12px;
  width: 2px; background: var(--acc);
  opacity: 0; transform: scaleY(.3); transform-origin: center;
  transition: opacity var(--tr-fast), transform var(--tr);
}
.mod:hover, .mod:focus-visible {
  background-color: var(--bg-3);
  border-color: var(--acc-line);
  /* Elevación algo mayor + escala mínima: se siente táctil sin saltar. */
  transform: translateY(-3px) scale(1.008);
  box-shadow: var(--sh-2), 0 0 0 1px var(--acc-line) inset;
  transition:
    transform .22s cubic-bezier(.34,1.4,.64,1),
    box-shadow .22s ease,
    border-color .16s ease,
    background-color .16s ease;
}
.mod:hover::before, .mod:focus-visible::before { opacity: 1; transform: scaleY(1); }

.mod__tile {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  color: var(--ink-2);
  background: var(--bg-inset);
  border: 1px solid var(--line-1);
  border-radius: var(--r-sm);
  transition: color var(--tr-fast), border-color var(--tr-fast), background-color var(--tr-fast);
}
.mod:hover .mod__tile, .mod:focus-visible .mod__tile {
  color: var(--acc-ink);
  border-color: var(--acc-line);
  background: var(--acc-soft);
}
.mod__body { min-width: 0; flex: 1; }
.mod__n {
  font-family: var(--f-display);
  font-size: 13.5px; font-weight: 600; letter-spacing: .02em;
  color: var(--ink-1); line-height: 1.25;
  display: block;
  transition: color var(--tr-fast);
}
/* El nombre del módulo se tiñe con el acento al pasar por encima. */
.mod:hover .mod__n, .mod:focus-visible .mod__n { color: var(--acc-ink); }
.mod__d { font-size: 11.5px; line-height: 1.45; color: var(--ink-2); margin-top: 4px; }

/* La flecha reserva su espacio siempre: aparece en hover sin mover el texto. */
.mod__go {
  flex: none; align-self: center;
  margin-left: var(--sp-1);
  color: var(--acc-ink);
  opacity: 0; transform: translateX(-5px);
  transition: opacity var(--tr-fast), transform var(--tr);
}
.mod:hover .mod__go, .mod:focus-visible .mod__go { opacity: 1; transform: translateX(0); }


/* ============================================================================
   17. TABLAS
       Base para todos los listados del ERP. Envolver SIEMPRE en .tabla-wrap
       para que una tabla ancha se desplace dentro de su caja y nunca provoque
       scroll horizontal en la página.
       Marcado: <div class="tabla-wrap"><table class="tabla">…</table></div>
   ============================================================================ */
.tabla-wrap {
  width: 100%;
  overflow-x: auto;
  border: 1px solid var(--line-1);
  border-radius: var(--r-md);
  background: var(--bg-2);
}

.tabla {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
  color: var(--ink-2);
}

.tabla thead th {
  position: sticky; top: 0; z-index: 1;
  padding: var(--sp-3) var(--sp-4);
  text-align: left; white-space: nowrap;
  font-family: var(--f-mono); font-size: 9.5px; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-3);
  background: var(--bg-1);
  border-bottom: 1px solid var(--line-1);
}

.tabla tbody td {
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line-2);
  vertical-align: middle;
}
.tabla tbody tr:last-child td { border-bottom: none; }
.tabla tbody tr { transition: background-color var(--tr-fast); }
.tabla tbody tr:hover { background: var(--bg-3); }

/* Fila seleccionada: filo de acento sin desplazar el contenido. */
.tabla tbody tr.is-active td { background: var(--acc-soft); color: var(--ink-1); }
.tabla tbody tr.is-active td:first-child { box-shadow: inset 2px 0 0 var(--acc); }

/* Primera columna = identificador de la fila: se lee como título. */
.tabla tbody td:first-child { color: var(--ink-1); font-weight: 500; }

/* Modificadores de celda -------------------------------------------------- */
.tabla .num-col,
.tabla td.num-col,
.tabla th.num-col {
  font-family: var(--f-mono); font-variant-numeric: tabular-nums;
  text-align: right; color: var(--ink-1);
}
.tabla .col-acciones { width: 1%; white-space: nowrap; text-align: right; }

/* Variantes de densidad y rayado ------------------------------------------ */
.tabla--compacta tbody td { padding: var(--sp-2) var(--sp-3); }
.tabla--compacta thead th { padding: var(--sp-2) var(--sp-3); }
.tabla--rayada tbody tr:nth-child(even) { background: var(--bg-inset); }
.tabla--rayada tbody tr:nth-child(even):hover { background: var(--bg-3); }

/* Estado vacío del listado. */
.tabla__vacio {
  padding: var(--sp-8) var(--sp-4);
  text-align: center;
  font-family: var(--f-mono); font-size: 11.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3);
}

/* Título de la tabla, cuando se usa <caption>. */
.tabla caption {
  padding: var(--sp-3) var(--sp-4);
  text-align: left;
  font-family: var(--f-display); font-size: 13px; font-weight: 600;
  letter-spacing: .10em; text-transform: uppercase; color: var(--ink-1);
}


/* ============================================================================
   18. PIE DE PÁGINA
   ============================================================================ */
.foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); flex-wrap: wrap;
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line-1);
  font-family: var(--f-mono); font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3);
}


} /* ── fin de @layer pvm-componentes (secciones 12 a 18) ─────────────────── */


/* ============================================================================
   19. MOVIMIENTO — @keyframes Y ENTRADA ESCALONADA
       Todas las animaciones del sistema viven aquí, juntas, para poder
       auditarlas de un vistazo (y desactivarlas en bloque en la sección 20).

       Van FUERA de la capa: los @keyframes se resuelven por nombre, no por
       cascada, y la sección 20 necesita poder anular animaciones de cualquier
       módulo.
   ============================================================================ */

/* Trazado de la línea de una gráfica: dibuja el dato de izquierda a derecha. */
@keyframes trazar       { to { stroke-dashoffset: 0; } }

/* Crecimiento del área bajo la línea, desde la base. */
@keyframes crecer-area  { to { opacity: .13; transform: scaleY(1); } }

/* Aparición de la marca del último valor, con un rebote corto. */
@keyframes marcar       { to { opacity: 1; transform: scale(1); } }

/* Columnas que suben desde la base. */
@keyframes subir-barra  { from { transform: scaleY(0); transform-origin: bottom; transform-box: fill-box; } }

/* Latido de la marca mientras el cursor está sobre el KPI. */
@keyframes latir {
  0%, 100% { transform: scale(1);    opacity: 1; }
  50%      { transform: scale(1.35); opacity: .85; }
}

/* Entrada de bloques al cargar la pantalla. */
@keyframes entra {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* Utilidad de entrada escalonada.
   Uso: <section class="anima" style="--d:120ms"> — cada bloque recibe su
   propio retardo, así el tablero se "arma" por capas en lugar de aparecer
   de golpe. Sin --d, entra de inmediato. */
.anima {
  opacity: 0;
  animation: entra 520ms var(--ease-out) forwards;
  animation-delay: var(--d, 0ms);
}


/* ============================================================================
   20. PREFERS-REDUCED-MOTION
       Si el usuario pidió menos movimiento en su sistema operativo, todo el
       movimiento se anula: nada de trazados, rebotes ni desplazamientos.
       Los elementos quedan en su estado FINAL, nunca ocultos.

       NOTA para el JS: las gráficas .viz arrancan ocultas y se revelan con
       .viz--go. El script debe añadir .viz--go a todas las gráficas cuando
       matchMedia('(prefers-reduced-motion: reduce)') coincida o cuando no
       exista IntersectionObserver, para que el dato se vea igualmente.
   ============================================================================ */
@media (prefers-reduced-motion: reduce) {

  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }

  /* Los bloques con entrada escalonada se muestran ya colocados. */
  .anima { opacity: 1; transform: none; }

  /* Sin desplazamientos al pasar el cursor. */
  .mod:hover, .mod:focus-visible,
  .kpi:hover, .card--link:hover, .btn:active { transform: none; }

  /* Las gráficas se muestran completas, sin trazarse. */
  .viz .linea { stroke-dasharray: none; stroke-dashoffset: 0; }
  .viz .area  { opacity: .13; transform: none; }
  .viz .marca { opacity: 1; transform: none; }
}


/* ============================================================================
   21. RESPONSIVE — sin scroll horizontal en ningún ancho
       Puntos de corte: 1180 (portátil estrecho), 960 (tableta: la navegación
       pasa a barra horizontal), 720 (móvil grande), 480 (móvil).

       Va DENTRO de la capa de componentes porque toca nombres genéricos
       (.btn, .card__head, .kpis, .mods): sin capa, la regla de 480px
       ".btn { width:100% }" le ganaría a la del módulo en móvil.
   ============================================================================ */
@layer pvm-componentes {

/* --- 1180px: se estrecha el panel lateral y se reduce el margen ---------- */
@media (max-width: 1180px) {
  :root { --nav-w: 216px; }
  .main { padding: var(--sp-6) var(--sp-5) var(--sp-8); }
}

/* --- 960px: la navegación lateral se convierte en barra horizontal ------- */
@media (max-width: 960px) {
  .app { grid-template-columns: minmax(0, 1fr); }

  .nav {
    position: static; height: auto;
    flex-direction: row; align-items: center; gap: var(--sp-1);
    overflow-x: auto; overflow-y: hidden;
    padding: var(--sp-2) var(--sp-4);
    border-right: none; border-bottom: 1px solid var(--line-1);
  }
  .nav__label, .nav__sep, .plant { display: none; }
  .nav__item { width: auto; flex: none; white-space: nowrap; padding: 8px var(--sp-3); }
  .nav__item span { flex: none; }
  /* El marcador de activo pasa de filo vertical a subrayado. */
  .nav__item::before {
    top: auto; bottom: 0; left: 8px; right: 8px;
    width: auto; height: 0; transform: none;
  }
  .nav__item.is-active::before { height: 2px; }

  .brand__txt { display: none; }
  .search { max-width: none; }
}

/* --- 720px: se sueltan los adornos y las rejillas pasan a una columna ---- */
@media (max-width: 720px) {
  .appbar { gap: var(--sp-3); padding: 0 var(--sp-3); }
  .search .kbd { display: none; }
  .user__txt { display: none; }
  .main { padding: var(--sp-5) var(--sp-4) var(--sp-8); }
  .hero { align-items: flex-start; }
  .mods { grid-template-columns: minmax(0, 1fr); }
  .grupo__d { display: none; }
  .card__head { flex-wrap: wrap; }
}

/* --- 480px: una sola columna en todo ------------------------------------- */
@media (max-width: 480px) {
  .hero__meta { gap: var(--sp-4); }
  .kpis { grid-template-columns: minmax(0, 1fr); }
  .btn { width: 100%; }
  .card__actions { width: 100%; }
}

} /* ── fin de @layer pvm-componentes (sección 21) ─────────────────────────── */


/* ============================================================================
   22. UTILIDADES
       Mínimas y sin colores literales. No convertir esto en un framework de
       utilidades: si algo se repite, merece ser un componente.
   ============================================================================ */
.u-mono      { font-family: var(--f-mono); font-variant-numeric: tabular-nums; }
.u-display   { font-family: var(--f-display); }
.u-ink-2     { color: var(--ink-2); }
.u-ink-3     { color: var(--ink-3); }
.u-acc       { color: var(--acc-ink); }
.u-nowrap    { white-space: nowrap; }
.u-truncar   { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.u-fila      { display: flex; align-items: center; gap: var(--sp-2); }
.u-fila-fin  { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; }
.u-sep       { height: 1px; background: var(--line-2); border: 0; margin: var(--sp-4) 0; }
.u-oculto    { display: none !important; }

/* Impresión: fuera cromos, fondos y elementos de navegación. */
@media print {
  .appbar, .nav, .skip-link, .iconbtn, .themebtn, .btn { display: none !important; }
  body { background: #fff; color: #000; }
  .app { display: block; }
  .main { padding: 0; }
  .card, .kpi, .mod, .tabla-wrap { box-shadow: none; border-color: #999; break-inside: avoid; }
}
