/* ============================================================================
   GV-UI — el sistema de diseño de Gestión Virgilio.   v29.76 (Luis, 13/10/2026)
   ----------------------------------------------------------------------------
   "quiero que agarremos una filosofía de diseño visual / front / usabilidad
    moderna y que cortemos con la basura. Buscamos que sea rápidamente procesable
    visualmente cualquier pantalla de esta aplicación."

   ESTE ARCHIVO ES LA FUENTE. Un módulo nuevo NO escribe sus propios px ni sus
   propios hex: usa estos tokens y estas clases. Lo que se midió el 13/10 y lo
   justifica: index.html tenía 302 colores y 38 tamaños de letra distintos, y
   cada módulo (.js) escribía su propio <style> con su propia escala.

   De dónde salen los números y por qué: docs/GV-UI.md.
   Los contrastes están MEDIDOS con la fórmula WCAG 2.x, no estimados: el número
   va al lado de cada color. Mínimo AA = 4,5:1 para texto chico, 3:1 para texto
   grande (≥ 24 px, o ≥ 19 px en negrita) y para bordes de control.

   ⚠ El que toca este archivo cambia TODA la app. Antes: docs/GV-UI.md y el
   agente `disenador-gvui`. Candado: tests/gv-ui-sistema.cjs.
   ============================================================================ */

:root {
  /* ── Tipografía ────────────────────────────────────────────────────────────
     6 pasos. Saltos de 2 px en el rango denso (Carbon y Fluent hacen lo mismo:
     un ratio modular de 1,25 da 17,5 px, que no sirve). 14 px es el PISO de un
     dato; 11 y 12 son sólo para rótulo o metadato, nunca para el número. */
  --gv-fs-xs:   11px;   /* rótulo de chip, metadato */
  --gv-fs-sm:   12px;   /* encabezado de columna, nota al pie */
  --gv-fs-md:   14px;   /* EL TEXTO: dato de tabla, cuerpo. Nunca menos. */
  --gv-fs-lg:   16px;   /* veredicto, título de sección */
  --gv-fs-xl:   20px;   /* código de la cosa en una tarjeta de lista */
  --gv-fs-2xl:  30px;   /* título de la cosa en el detalle */
  --gv-fs-hero: 46px;   /* EL DATO PRINCIPAL. Uno por pantalla. */
  --gv-lh:       1.35;
  --gv-font: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;

  /* ── Espaciado ─ base 4, con el 2 para lo micro (igual que Carbon) ──────── */
  --gv-sp-1:  2px;  --gv-sp-2:  4px;  --gv-sp-3:  8px;  --gv-sp-4: 12px;
  --gv-sp-5: 16px;  --gv-sp-6: 24px;  --gv-sp-7: 32px;  --gv-sp-8: 48px;

  /* ── Alto de fila de tabla ─ tres niveles separados por 8 px ────────────── */
  --gv-row-compact: 32px;
  --gv-row:         40px;
  --gv-row-roomy:   48px;

  /* ── Radio ─ dos valores y nada más ─────────────────────────────────────── */
  --gv-r-sm: 10px;  /* botón, chip, celda */
  --gv-r:    14px;  /* tarjeta, panel */
  --gv-r-pill: 999px;

  /* ── Color ───────────────────────────────────────────────────────────────
     El número es el contraste MEDIDO contra el fondo de la app (--gv-bg).
     Un color que no llega a 4,5 NO se usa para texto. */
  --gv-bg:        #f6f7f9;  /* fondo de pantalla */
  --gv-surface:   #ffffff;  /* tarjeta, panel, fila */
  --gv-surface-2: #f1f5f9;  /* chip neutro, encabezado de tabla */
  --gv-ink:       #0f172a;  /* texto                     16,65 */
  --gv-ink-2:     #475569;  /* texto secundario, rótulo   7,07 */
  --gv-line:      #e2e8f0;  /* borde de tarjeta */
  --gv-line-soft: #eef2f7;  /* divisor de fila de tabla */
  --gv-muted:     #94a3b8;  /* SÓLO líneas e íconos decorativos: 2,39 — NUNCA texto */
  --gv-dark:      #0f172a;  /* barra superior */

  --gv-error:     #b91c1c;  /*  6,04  */
  --gv-ok:        #15803d;  /*  4,68  */
  --gv-warn:      #92400e;  /*  6,61  — el ámbar de TEXTO. #d97706 da 2,97: no se usa. */
  --gv-info:      #0f62fe;  /*  4,67  */
  --gv-error-bg:  #fef4f4;  --gv-error-line: #fecaca;
  --gv-ok-bg:     #f0fdf4;  --gv-ok-line:    #86efac;
  --gv-warn-bg:   #fffbeb;  --gv-warn-line:  #fcd34d;
  /* El amarillo pleno sólo como FONDO con texto negro (10,75). Como texto sobre
     blanco mide 1,68 y es ilegible: por eso no hay token de texto amarillo. */
  --gv-warn-solid: #f1c21b;  --gv-on-warn: #161616;

  /* ── Blanco de toque del celular del operario ────────────────────────────
     WCAG 2.5.5 (AAA) y Apple HIG: 44 px. Es el ÁREA, no el ícono. */
  --gv-tap: 44px;
}

/* ── Primitivas ──────────────────────────────────────────────────────────────
   Se aplican dentro de un contenedor con la clase .gv, nunca al documento: el
   index.html tiene su propio CSS global (button{width:100%} y demás) y esto no
   lo puede pisar fuera de su pantalla. */
.gv { font-family: var(--gv-font); color: var(--gv-ink); background: var(--gv-bg);
      -webkit-font-smoothing: antialiased; }
.gv *, .gv *::before, .gv *::after { box-sizing: border-box; }

/* El dato principal. UNO por pantalla, y es el texto más grande que se ve. */
.gv-hero { font-size: var(--gv-fs-hero); font-weight: 800; line-height: 1.02;
           letter-spacing: -1px; font-variant-numeric: tabular-nums; }
/* Rótulo de lo que sea: 1 o 2 palabras, SIN la fórmula entre paréntesis. */
.gv-label { font-size: var(--gv-fs-xs); letter-spacing: 1px; text-transform: uppercase;
            color: var(--gv-ink-2); font-weight: 700; }
.gv-sub   { font-size: 13.5px; color: var(--gv-ink-2); }

.gv-card  { background: var(--gv-surface); border: 1px solid var(--gv-line);
            border-radius: var(--gv-r); padding: var(--gv-sp-4) var(--gv-sp-5); }

/* El veredicto: UNA línea, arriba de todo, con la severidad en el borde izquierdo
   Y en la palabra. El color nunca va solo (WCAG 1.4.1). */
.gv-state { display: flex; align-items: center; gap: var(--gv-sp-4); flex-wrap: wrap;
            background: var(--gv-surface); border: 1px solid var(--gv-line);
            border-left: 5px solid var(--gv-muted); border-radius: 12px;
            padding: var(--gv-sp-4) var(--gv-sp-5); }
.gv-state .v { font-size: var(--gv-fs-lg); font-weight: 700; flex: 1; min-width: 180px; }
.gv-state.alta  { border-left-color: var(--gv-error); } .gv-state.alta  .v { color: var(--gv-error); }
.gv-state.media { border-left-color: var(--gv-warn); }  .gv-state.media .v { color: var(--gv-warn); }
.gv-state.ok    { border-left-color: var(--gv-ok); }    .gv-state.ok    .v { color: var(--gv-ok); }

/* Un hallazgo = una línea, con punto de color. */
.gv-item { display: flex; gap: var(--gv-sp-3); align-items: flex-start;
           background: var(--gv-surface); border: 1px solid var(--gv-line);
           border-radius: 11px; padding: var(--gv-sp-3) var(--gv-sp-4);
           margin-bottom: 7px; font-size: 14.5px; line-height: var(--gv-lh); }
.gv-item .dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 9px;
                margin-top: 6px; background: var(--gv-muted); }
.gv-item.alta { background: var(--gv-error-bg); border-color: var(--gv-error-line); }
.gv-item.alta .dot  { background: var(--gv-error); }
.gv-item.media { border-color: var(--gv-warn-line); }
.gv-item.media .dot { background: var(--gv-warn); }
.gv-item.baja { color: var(--gv-ink-2); }

/* Lo explicativo va plegado. El chevron hace de affordance sin emoji. */
.gv details { background: var(--gv-surface); border: 1px solid var(--gv-line);
              border-radius: 12px; margin-bottom: var(--gv-sp-3); overflow: hidden; }
.gv summary { cursor: pointer; padding: 11px var(--gv-sp-5); font-size: 14.5px;
              font-weight: 700; color: var(--gv-ink); list-style: none;
              display: flex; align-items: center; gap: var(--gv-sp-3);
              min-height: var(--gv-tap); }
.gv summary::-webkit-details-marker { display: none; }
.gv summary::before { content: '\203A'; display: inline-block; font-size: 19px;
                      color: var(--gv-muted); transform: rotate(0deg);
                      transition: transform .15s; line-height: 1; }
.gv details[open] summary::before { transform: rotate(90deg); }
.gv summary .n { font-weight: 500; color: var(--gv-ink-2); font-size: 13.5px; }

/* ── Tabla densa ─────────────────────────────────────────────────────────────
   Encabezado en sentence case (Carbon pasó de title case a sentence case en la
   v10), divisores horizontales finos y SIN zebra: con color semántico en juego
   el zebra pelea con el dato. Cifras tabulares para que la columna no baile. */
.gv-tbl { border-collapse: collapse; width: 100%; font-size: var(--gv-fs-md);
          font-variant-numeric: tabular-nums; }
.gv-tbl th { background: var(--gv-surface-2); color: var(--gv-ink-2); font-size: var(--gv-fs-sm);
             font-weight: 700; padding: 7px var(--gv-sp-3); text-align: center;
             line-height: 1.2; position: sticky; top: 0;
             border-bottom: 1px solid var(--gv-line); }
.gv-tbl th, .gv-tbl td { height: var(--gv-row); }
.gv-tbl.compact th, .gv-tbl.compact td { height: var(--gv-row-compact); padding: var(--gv-sp-2) var(--gv-sp-3); }
.gv-tbl.roomy th, .gv-tbl.roomy td { height: var(--gv-row-roomy); padding: var(--gv-sp-4) var(--gv-sp-5); }
.gv-tbl td { padding: 6px var(--gv-sp-3); text-align: center;
             border-top: 1px solid var(--gv-line-soft); white-space: nowrap; }
.gv-tbl td.t { text-align: left; color: var(--gv-ink-2);
               max-width: 210px; overflow: hidden; text-overflow: ellipsis; }
/* Fila problemática: fondo + barra a la izquierda. El color NUNCA solo: la fila
   además tiene que decirlo con un número en rojo o una palabra. */
.gv-tbl tr.mala td { background: var(--gv-error-bg); }
.gv-tbl tr.mala td:first-child { box-shadow: inset 4px 0 0 var(--gv-error); }
.gv-tblwrap { overflow: auto; border-top: 1px solid var(--gv-line-soft); }

/* ── Controles ───────────────────────────────────────────────────────────── */
.gv button { width: auto; margin-top: 0; padding: 7px 13px; font-size: var(--gv-fs-md);
             line-height: 1.2; border-radius: var(--gv-r-sm); border: 1px solid #d7dde5;
             background: var(--gv-surface); color: var(--gv-ink); cursor: pointer;
             font-weight: 600; min-height: 34px; }
.gv button:hover { border-color: var(--gv-muted); }
.gv input, .gv select { width: auto; margin-top: 0; font: inherit;
             font-size: 15px; padding: 6px 10px; border: 1px solid #d7dde5;
             border-radius: var(--gv-r-sm); background: var(--gv-surface); }
.gv-chip { padding: 5px var(--gv-sp-4); border-radius: var(--gv-r-pill);
           border: 1px solid var(--gv-line); background: var(--gv-surface);
           cursor: pointer; color: var(--gv-ink-2); font-size: var(--gv-fs-md); }
.gv-chip.on { background: var(--gv-dark); color: #fff; border-color: var(--gv-dark);
              font-weight: 700; }
/* La pastilla de estado lleva texto, no sólo color (WCAG 1.4.1). */
.gv-badge { display: inline-block; border-radius: var(--gv-r-pill); padding: 2px 10px;
            font-size: 12.5px; font-weight: 700; }
.gv-badge.err  { background: var(--gv-error); color: #fff; }
.gv-badge.ok   { background: var(--gv-ok-bg); color: var(--gv-ok); }
.gv-badge.warn { background: var(--gv-warn-solid); color: var(--gv-on-warn); }
.gv-badge.info { background: #eef4ff; color: var(--gv-info); }

/* ── Estados de la pantalla ──────────────────────────────────────────────── */
.gv-msg { text-align: center; padding: var(--gv-sp-7) var(--gv-sp-6); color: var(--gv-ink-2);
          font-size: 15px; }
/* Una lectura ROTA se dice: no es «no hay». Regla del CLAUDE.md. */
.gv-err { text-align: center; padding: var(--gv-sp-6); color: var(--gv-error); font-weight: 700; }

/* ── Celular ─────────────────────────────────────────────────────────────── */
@media (max-width: 560px) {
  .gv { --gv-fs-hero: 38px; --gv-fs-2xl: 25px; }
  /* El operario trabaja de pie y con guantes: todo lo que se toca, 44 px. */
  .gv button, .gv-chip, .gv summary { min-height: var(--gv-tap); }
}
