/* AISLAR OBRAS — Design tokens */
:root {
  /* Verde productividad como primario */
  --brand-50:  oklch(0.97 0.02 155);
  --brand-100: oklch(0.93 0.05 155);
  --brand-200: oklch(0.86 0.09 155);
  --brand-300: oklch(0.78 0.13 155);
  --brand-400: oklch(0.70 0.15 155);
  --brand-500: oklch(0.62 0.16 155);
  --brand-600: oklch(0.54 0.15 155);
  --brand-700: oklch(0.44 0.13 155);
  --brand-800: oklch(0.34 0.10 155);
  --brand-900: oklch(0.24 0.06 155);

  /* Neutros cálidos (zinc-warm) */
  --ink-0:   #ffffff;
  --ink-50:  #fafaf9;
  --ink-100: #f4f4f1;
  --ink-150: #ecece8;
  --ink-200: #e4e3de;
  --ink-300: #cac8c0;
  --ink-400: #767368;  /* WCAG AA: texto muteado ≥4.5:1 sobre blanco/cards (antes #a3a098 = 2.6:1) */
  --ink-500: #75726a;
  --ink-600: #54514a;
  --ink-700: #3a3833;
  --ink-800: #25241f;
  --ink-900: #15140f;

  /* Estados */
  --warn:    oklch(0.75 0.16 75);
  --warn-bg: oklch(0.96 0.04 75);
  --danger:  oklch(0.57 0.20 25);
  --danger-bg: oklch(0.96 0.03 25);
  --info:    oklch(0.62 0.13 240);
  --info-bg: oklch(0.96 0.03 240);
  --ok:      var(--brand-500);
  --ok-bg:   var(--brand-50);

  /* Typography */
  --font-ui: 'Inter', -apple-system, system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;

  /* Radii */
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-xl: 20px;
  --r-2xl: 28px;

  /* Shadows */
  --sh-sm: 0 1px 2px rgba(20,20,15,0.05), 0 1px 1px rgba(20,20,15,0.04);
  --sh-md: 0 2px 4px rgba(20,20,15,0.04), 0 6px 16px rgba(20,20,15,0.06);
  --sh-lg: 0 8px 24px rgba(20,20,15,0.08), 0 24px 56px rgba(20,20,15,0.10);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; font-family: var(--font-ui); color: var(--ink-800); -webkit-font-smoothing: antialiased; }
body { background: var(--ink-100); }

/* Mono utility */
.mono { font-family: var(--font-mono); font-feature-settings: 'tnum' 1; }
.tnum { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; }

/* ═══════════════════════════════════════════════════════════════════════════════
   AGREGADO — cubre el hueco contra el handoff de diseño del 27/08.
   Va al final del bloque :root de tokens.css, o como un segundo :root debajo.

   TODO ES ADITIVO A PROPOSITO: no se toca ni un token vigente. --ink-500 tiene
   1114 referencias y --ink-200 949; cambiar un valor que ya está en uso repinta
   la app entera de una, y con Babel en el navegador no hay build que lo frene.

   Los valores de hue 300 y los tamaños de puesto NO son inventados: salen medidos
   de docs/handoff/2026-08-27-prototipo-puestos.dc.html, donde ya están hardcodeados.
   ═══════════════════════════════════════════════════════════════════════════════ */
:root {

  /* ── Movido a mano · hue 300 ────────────────────────────────────────────────
     Caballete cambiado, marca fuera de asignación. Era el único estado del
     handoff sin token. Valores exactos del prototipo (líneas 1032 y 1890-1891). */
  --moved:        oklch(0.35 0.13 300);  /* texto e ícono */
  --moved-bg:     oklch(0.95 0.05 300);  /* fondo del chip suave */
  --moved-strong: oklch(0.90 0.09 300);  /* fondo de la pieza movida, en el plano */
  --moved-border: oklch(0.78 0.11 300);

  /* ── Rampa de warn que YA SE USA y no estaba declarada ──────────────────────
     admin-gastos.jsx la referencia en 13 lugares. Hoy esos avisos salen sin
     ámbar: la var inválida deja el fondo transparente y el borde en currentColor.
     Esto no es diseño nuevo, es cerrar un bug vivo. Hue 75, el de --warn. */
  --warn-50:  oklch(0.96 0.04 75);   /* = --warn-bg; se declara aparte porque es el nombre que el código pide */
  --warn-200: oklch(0.87 0.09 75);   /* borde */
  --warn-700: oklch(0.47 0.11 75);   /* texto sobre --warn-50 · ~7:1, AA holgado */

  /* ── Las rampas COMPLETAS de estado ─────────────────────────────────────────
     Los .jsx del taller referencian 85 escalones de aviso y error que no existían.
     Todos traen fallback hexadecimal, así que no se rompía nada — y por eso nadie
     lo vio: simplemente el ámbar y el rojo de la app eran los de Tailwind
     (#fffbeb, #92400e, #b91c1c) en vez de la familia oklch del diseño. Dos paletas
     conviviendo, una declarada y otra escondida adentro de los fallbacks.

     `--warn-800` solo aparece 27 veces y `--danger-700` diez. Completar las rampas
     alinea los 85 de una y no toca una sola línea de JSX.

     Mismos hues que los base: warn 75, danger 25, info 240. Los escalones 500 SON
     `--warn` / `--danger` / `--info`, para que la rampa y el nombre corto no
     puedan divergir el día que alguien ajuste uno de los dos. */
  --warn-100: oklch(0.93 0.06 75);
  --warn-300: oklch(0.81 0.13 75);
  --warn-400: oklch(0.78 0.15 75);
  --warn-500: var(--warn);
  --warn-600: oklch(0.62 0.14 75);
  --warn-800: oklch(0.38 0.09 75);   /* texto fuerte sobre ámbar claro */
  --warn-900: oklch(0.29 0.07 75);

  --danger-50:  var(--danger-bg);
  --danger-100: oklch(0.93 0.05 25);
  --danger-200: oklch(0.87 0.09 25);
  --danger-300: oklch(0.79 0.14 25);
  --danger-400: oklch(0.67 0.19 25);
  --danger-500: var(--danger);
  --danger-600: oklch(0.51 0.19 25);
  --danger-700: oklch(0.44 0.16 25);
  --danger-800: oklch(0.36 0.13 25);
  --danger-900: oklch(0.28 0.10 25);

  --info-50:  var(--info-bg);
  --info-100: oklch(0.92 0.05 240);
  --info-200: oklch(0.86 0.08 240);
  --info-300: oklch(0.78 0.11 240);
  --info-500: var(--info);
  --info-600: oklch(0.55 0.13 240);
  --info-700: oklch(0.46 0.12 240);
  --info-800: oklch(0.37 0.10 240);
  --info-900: oklch(0.29 0.08 240);

  /* ── Sombra referenciada y no declarada ─────────────────────────────────────
     admin-config.jsx:122 pide var(--sh-xl) en el modal: hoy queda sin sombra. */
  --sh-xl: 0 16px 48px rgba(20,20,15,0.12), 0 40px 80px rgba(20,20,15,0.14);

  /* ── Alias de nombres que el código usa y acá no existían ───────────────────
     Se declaran ACÁ y no se renombra en los .jsx a propósito: son ocho archivos
     distintos, y uno de ellos (admin-fichajes.jsx) lo está editando otra sesión.
     Un alias de una línea no puede pisarle un merge a nadie.

     Las tres primeras NO traían fallback, así que hoy la declaración entera es
     inválida y el navegador la descarta:

       · `--warning` — admin-empleados.jsx:3896 la usa para pintar de ámbar al
         que tiene `rol: 'pendiente'`, que NO es "sin asignar": es una BAJA. Hoy
         ese renglón sale del color del texto normal y no se distingue de nadie.
         admin-obras.jsx:2342 la usa para la obra sin coordenadas.
       · `--ink-250` — recursos.jsx:1012, el borde punteado de una zona de drop.
         Sin la var, el borde cae a `currentColor` y se pinta del color del texto.
       · El resto traen fallback y sólo estaban fuera de la paleta. */
  --warning: var(--warn);
  --good:    var(--brand-600);
  --ink-250: oklch(0.90 0.004 85);   /* entre --ink-200 y --ink-300 */
  --ok-50:   var(--brand-50);
  --ok-700:  var(--brand-700);
  --danger-border: var(--danger-200);
  --azul-50:  var(--info-50);
  --azul-800: var(--info-800);

  /* ── Radios que faltaban ────────────────────────────────────────────────────
     6 / 14 / 20 ya estaban como --r-sm / --r-lg / --r-xl.
     OJO: --r-md vale 10px y el handoff pide 9 para botones. NO se pisa --r-md
     (shared.jsx:274 y :287 lo usan, y el prototipo usa 9 y 10 como radios
     distintos, 23 y 30 veces): se agrega --r-btn al lado. */
  --r-btn:    9px;             /* botones */
  --r-item:  12px;             /* ítems de lista */
  --r-puesto: 16px;            /* bloques de los puestos dedicados */
  --r-chip:  var(--r-sm);      /* 6px  — alias legible */
  --r-sec:   var(--r-lg);      /* 14px — secciones */
  --r-pill:  var(--r-xl);      /* 20px — pills */

  /* ── Escala tipográfica ─────────────────────────────────────────────────────
     No existía ninguna. OJO AL USARLA: taller.jsx escribe fontSize como NUMERO
     (fontSize: 13), y un número no resuelve var(). Cada call site que migre tiene
     que pasar a string: fontSize: 'var(--fs-nav)'. Declarar el token no cambia
     nada solo. */
  --fs-label:     9.5px;   /* labels uppercase */
  --fs-meta:       11px;
  --fs-body-sm:    12px;
  --fs-body:     12.5px;
  --fs-nav:      13.5px;
  --fs-item:     15.5px;   /* título de ítem */
  --fs-screen:     21px;   /* título de pantalla */
  --fs-kpi:        24px;
  --fs-puesto:     52px;   /* el dato que se lee de lejos */
  --fs-puesto-xl:  86px;   /* el número único de la pantalla */

  --ls-label:      0.08em;
  --ls-label-wide: 0.10em;
  --ls-title:     -0.02em;
  --fw-label: 700;
  --fw-title: 800;

  /* ── Hit targets ────────────────────────────────────────────────────────────
     Con guantes. El 56 es el de los botones ±1/±5 de la medida, que es la
     decisión que más se toca en el puesto del que mide. */
  --hit-min:    44px;   /* mínimo en listas */
  --hit-step:   56px;   /* ±1 / ±5 de la medida */
  --hit-puesto: 112px;  /* primario de los puestos dedicados */
}

/* Prefijo tk- a propósito: los .jsx comparten scope global y "label" es demasiado
   genérico para dejarlo suelto. Hoy no hay colisión (0 className="label"). */
.tk-label {
  font-size: var(--fs-label);
  font-weight: var(--fw-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ink-500);
}

/* El dato que se lee de lejos, SIEMPRE mono tabular: si no, el número cambia de
   ancho mientras cuenta y salta la pantalla entera. */
.tk-dato {
  font-family: var(--font-mono);
  font-size: var(--fs-puesto);
  font-weight: var(--fw-title);
  letter-spacing: var(--ls-title);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  line-height: 1;
}
.tk-dato-xl { font-size: var(--fs-puesto-xl); }

/* .mono declara font-feature-settings pero no font-variant-numeric. Con
   JetBrains Mono da igual, pero si cae al fallback la diferencia se ve. */
.mono { font-variant-numeric: tabular-nums; }