:root{
  --navy:#1f3353; --navy2:#2e5a8c; --accent:#1565a0; --heading:#1f3353;
  --bg:#eef1f5; --card:#fff; --border:#dde3ea; --text:#1c2530; --muted:#6b7785;
  --surface2:#f4f7fb; --input-bg:#fff; --sidebar:linear-gradient(180deg,#24344f 0%,#1f3353 60%,#1a2c46 100%);
  --ok:#1b7a3d; --warn:#b8860b; --danger:#c0392b;
  --shadow:0 1px 2px rgba(16,24,40,.05),0 2px 8px rgba(16,24,40,.04);
  --shadow-lg:0 12px 32px rgba(16,24,40,.18);
  --radius:11px; --tr:.16s ease;
}
/* Tema oscuro: explícito (toggle) o por preferencia del sistema si no se forzó claro */
:root[data-theme="dark"]{
  --navy:#0e1826; --navy2:#3a6ea5; --accent:#5a9be0; --heading:#e9edf3;
  --bg:#0e131a; --card:#161d27; --border:#29323f; --text:#e5eaf1; --muted:#9aa7b6;
  --surface2:#1b2432; --input-bg:#0e131a; --sidebar:linear-gradient(180deg,#0d1826 0%,#0b1420 100%);
  --ok:#42c06c; --warn:#d9a441; --danger:#e5675b;
  --shadow:0 1px 2px rgba(0,0,0,.4); --shadow-lg:0 12px 32px rgba(0,0,0,.5);
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --navy:#0e1826; --navy2:#3a6ea5; --accent:#5a9be0;
    --bg:#0e131a; --card:#161d27; --border:#29323f; --text:#e5eaf1; --muted:#9aa7b6;
    --surface2:#1b2432; --input-bg:#0e131a; --sidebar:linear-gradient(180deg,#0d1826 0%,#0b1420 100%);
    --ok:#42c06c; --warn:#d9a441; --danger:#e5675b;
    --shadow:0 1px 2px rgba(0,0,0,.4); --shadow-lg:0 12px 32px rgba(0,0,0,.5);
  }
}
*{box-sizing:border-box}
body{margin:0;font-family:"Segoe UI",Roboto,Helvetica,Arial,sans-serif;background:var(--bg);color:var(--text);line-height:1.5}
a{color:var(--accent);text-decoration:none}
h1,h2{margin:0}

/* Layout */
.layout{display:flex;min-height:100vh}
.sidebar{width:250px;background:var(--sidebar);color:#fff;flex-shrink:0;display:flex;flex-direction:column}
.brand{padding:18px 18px 16px;border-bottom:1px solid rgba(255,255,255,.12)}
/* Logo y nombre en una fila; el subtítulo va debajo a todo el ancho porque
   no entra al lado del logo sin cortarse en 250px de barra. */
.brand-lockup{display:flex;align-items:center;gap:11px}
.brand-logo{height:34px;width:auto;flex-shrink:0;display:block}
.brand-title{font-weight:700;font-size:17px;letter-spacing:.5px;white-space:nowrap}
.brand-sub{font-size:12px;opacity:.8;margin-top:6px}
.sidebar nav{padding:8px 0 16px;display:flex;flex-direction:column;overflow-y:auto;flex:1}
/* Los enlaces llevan una guía izquierda (transparente en reposo) que se enciende
   al pasar el mouse y en el activo: es lo que los distingue de los títulos de grupo. */
/* =================================================================
   ÍCONOS (SVG de línea, src/iconos.js)
   Heredan el color del texto y se alinean como una letra más. El tamaño
   se fija acá y no en cada SVG para que todos midan lo mismo.
   ================================================================= */
.ico{width:17px;height:17px;flex:none;vertical-align:-3.5px}
.ico-tit{width:19px;height:19px;vertical-align:-4px;margin-right:8px;color:var(--accent)}
.ico.is-danger{color:var(--danger)}
.ico.is-warn{color:var(--warn)}
/* Botones y enlaces con ícono: el ícono no empuja al texto ni descoloca
   la línea de base — quedan centrados entre sí con una separación fija. */
.btn,.of-salida,.btn-link,.stat-link,.adj-chip,.sec-i,.ia-ico{display:inline-flex;align-items:center;gap:6px}
.btn{justify-content:center}

.sidebar nav a{color:#cdd7e3;padding:9px 18px 9px 15px;font-size:14px;
  display:flex;align-items:center;gap:10px;
  border-left:3px solid transparent;transition:background .12s,border-color .12s,color .12s}
/* En reposo el ícono va más apagado que la etiqueta: da jerarquía sin
   ensuciar el menú. En el activo toma el color del texto. */
.sidebar nav a .ico{opacity:.72}
.sidebar nav a:hover .ico,.sidebar nav a.active .ico{opacity:1}
.sidebar nav a:hover{background:rgba(255,255,255,.07);color:#fff;border-left-color:rgba(255,255,255,.4)}
.sidebar nav a.active{background:var(--accent);color:#fff;font-weight:600;border-left-color:#fff}
/* Los títulos de grupo no son clicables: van sin guía, más chicos, más apagados
   y separados por una línea que corta visualmente cada sección. */
.nav-group{margin:16px 18px 6px;padding-top:14px;border-top:1px solid rgba(255,255,255,.13);
  font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:1.3px;
  color:rgba(255,255,255,.45);cursor:default;user-select:none}

.main{flex:1;display:flex;flex-direction:column;min-width:0}
.topbar{display:flex;justify-content:space-between;align-items:center;background:var(--card);border-bottom:1px solid var(--border);padding:14px 24px;position:sticky;top:0;z-index:20}
.topbar h1{font-size:20px;color:var(--heading)}
.user{display:flex;align-items:center;gap:14px;font-size:13px;color:var(--muted)}
.user .rol{background:var(--surface2);border-radius:10px;padding:1px 8px;font-size:11px;color:var(--accent)}
.content{padding:24px;max-width:1200px;width:100%}
/* Pantallas anchas: cronograma y tableros. 1800 y no «sin límite» porque
   en un monitor muy grande una tabla de punta a punta se vuelve ilegible;
   con esto una pantalla de 1920 queda usada entera. */
.content.ancho{max-width:1800px}

/* Cards */
.card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius);padding:20px 22px;margin-bottom:20px;box-shadow:var(--shadow)}
.card h2{color:var(--heading);font-size:16px;border-bottom:2px solid var(--navy2);padding-bottom:8px;margin-bottom:14px}
.card h2 .ico-tit{color:var(--navy2)}
.card-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:14px}
.card-head h2{border:0;margin:0;padding:0}
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;margin-bottom:20px}
.stat{text-align:center}
.stat .stat-num{font-size:38px;font-weight:700;color:var(--heading)}
.stat .stat-label{color:var(--muted);font-size:13px}
.stat.danger .stat-num{color:var(--danger)} .stat.warn .stat-num{color:var(--warn)} .stat.ok .stat-num{color:var(--ok)}
.stat-link{display:block;margin-top:8px;font-size:12px}

/* Tables */
table{border-collapse:collapse;width:100%;font-size:14px}
th,td{border-bottom:1px solid var(--border);padding:9px 12px;text-align:left;vertical-align:middle}
th{background:var(--surface2);color:var(--heading);font-size:12px;text-transform:uppercase;letter-spacing:.4px}
tr:hover td{background:var(--surface2)}
.num{text-align:right;font-variant-numeric:tabular-nums}
td.danger,.num.danger{color:var(--danger);font-weight:600} .num.warn{color:var(--warn);font-weight:600}
.row-actions{display:flex;gap:8px;justify-content:flex-end}
/* Importes: la moneda adelante y cifras alineadas para poder compararlas. */
.num-money{font-variant-numeric:tabular-nums;white-space:nowrap}
.row-actions form{display:inline}
tr.row-link{cursor:pointer}
tr.row-link:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}

/* Badges */
.badge{display:inline-block;background:var(--surface2);color:var(--heading);border-radius:10px;padding:2px 9px;font-size:12px}
.badge.tipo-NC-mayor{background:#fdecea;color:var(--danger)}
.badge.tipo-NC-menor{background:#fff4e0;color:var(--warn)}
.badge.tipo-observacion{background:#eef2f6;color:var(--accent)}
.badge.estado-pendiente{background:#fff4e0;color:var(--warn)}
.badge.estado-aprobado{background:#e7f6ec;color:var(--ok)}
.badge.estado-descartado{background:#eef0f2;color:var(--muted)}
/* Badges por valor (campos con `badge:true`): semáforo de nivel de riesgo.
   Mismo criterio que los badges de arriba: fondo pastel fijo + color del token,
   legible en ambos temas. "Crítico" va en sólido para que salte a la vista.
   Las decisiones comerciales (Go/No Go y resultado de la revisión de
   requisitos) reusan el mismo semáforo: rojo = no se puede comprometer,
   ámbar = con condiciones, verde = adelante, gris = todavía sin definir. */
.badge.v-critico,.badge.v-intolerable,
.badge.v-no-go,.badge.v-rechazada-no-go{background:#c0392b;color:#fff;font-weight:600}
.badge.v-alto,.badge.v-importante{background:#fdecea;color:#c0392b;font-weight:600}
.badge.v-moderado,.badge.v-medio,
.badge.v-go-con-condiciones,.badge.v-aprobada-con-salvedades{background:#fff4e0;color:#8a6508;font-weight:600}
.badge.v-bajo,.badge.v-tolerable,
.badge.v-go,.badge.v-aprobada{background:#e7f6ec;color:#1b7a3d}
.badge.v-trivial,.badge.v-muy-bajo,
.badge.v-analisis-incompleto,.badge.v-pendiente-de-aclaracion-del-cliente{background:#eef2f6;color:#5b6773}
/* Satisfacción del cliente y reclamos. Mismo semáforo: rojo = obliga a
   abrir un tratamiento formal, ámbar = hay algo que atender, verde = el
   procedimiento se cumplió. "Sí"/"No" son del acuse de recibo y del cierre
   en plazo, donde el "Sí" es lo correcto; por eso la NC sistémica lleva
   etiquetas propias en vez de reusar esas dos. */
.badge.v-abrir-reclamo-rg-com-007{background:#c0392b;color:#fff;font-weight:600}
.badge.v-no{background:#fdecea;color:#c0392b;font-weight:600}
.badge.v-bajo-la-meta,.badge.v-oportunidad-de-mejora,
.badge.v-si-abrir-nc{background:#fff4e0;color:#8a6508;font-weight:600}
.badge.v-cumple-meta,.badge.v-si{background:#e7f6ec;color:#1b7a3d}
.badge.v-no-requiere-accion,.badge.v-no-corresponde,
.badge.v-en-curso{background:#eef2f6;color:#5b6773}
/* Estado del registro (Personal, Choferes, Vehículos, Calibración): verde lo
   que está vigente, ámbar lo que está fuera de servicio pero vuelve, rojo lo
   que ya no se usa. Es el mismo semáforo del resto del sistema. */
.badge.v-activo,.badge.v-vigente{background:#e7f6ec;color:#1b7a3d}
.badge.v-inactivo,.badge.v-en-reparacion,
.badge.v-fuera-de-servicio{background:#fff4e0;color:#8a6508}
.badge.v-baja,.badge.v-vencida,.badge.v-revocada{background:#fdecea;color:#c0392b}

/* Buttons */
.btn{display:inline-block;border:1px solid transparent;border-radius:7px;padding:8px 14px;font-size:13px;cursor:pointer;font-family:inherit}
.btn-primary{background:var(--accent);color:#fff} .btn-primary:hover{background:var(--navy2)}
.btn-ghost{background:transparent;border-color:var(--border);color:var(--text);transition:background var(--tr)} .btn-ghost:hover{background:var(--surface2)}
.btn-ghost.danger{color:var(--danger);border-color:#f0c7c2}
/* Volver a la pantalla anterior, arriba a la derecha de la ventana. */
.btn-volver{background:var(--danger);color:#fff;border-color:transparent;font-weight:600;white-space:nowrap}
.btn-volver:hover{filter:brightness(.92)}
/* La cabecera del formulario no lleva la línea inferior de .card h2: el
   título y el botón ya forman una banda propia. */
.form-card .card-head h2{border-bottom:0;padding-bottom:0;margin-bottom:0}

/* Tablero de ofertas: reusa las clases fb-* del flujo y sólo suma lo suyo. */
.of-ver{font-size:11px;font-weight:700;background:var(--surface2);color:var(--accent);
  border-radius:8px;padding:0 6px;margin-left:2px}
.of-monto{font-size:12px;font-weight:600;color:var(--heading);white-space:nowrap}
.of-ver-doc{font-size:12px;font-weight:600;color:var(--accent);white-space:nowrap}
.of-ver-doc:hover{text-decoration:underline}
/* La tarjeta entera abre la edición, igual que el renglón de una tabla. */
.fb-exp.is-click{cursor:pointer}
.fb-exp.is-click:hover{border-color:var(--accent)}
.fb-exp.is-click:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* El alcance de una oferta es un texto largo: en la tarjeta se recorta a
   cuatro renglones. El texto completo se lee en «Ver oferta». */
.of-board .fb-desc{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;white-space:pre-line}
.fb-pend{display:flex;flex-wrap:wrap;gap:10px}
.fb-pend .fb-exp{width:270px;max-width:100%}

/* Alta rápida en la cabecera de la primera columna: un "+" en la misma
   fila del título, para no gastar un renglón entero del tablero. */
.fb-add{display:inline-flex;align-items:center;justify-content:center;
  width:19px;height:19px;border-radius:50%;font-size:15px;font-weight:700;line-height:1;
  background:var(--accent);color:#fff;flex-shrink:0;text-decoration:none;margin-left:2px}
.fb-add:hover{filter:brightness(1.12)}

/* Salidas sin columna: la acción vive en la tarjeta porque no hay
   adónde arrastrarla (su tarjeta ya se ve en el otro tablero). */
.fb-salidas{display:flex;flex-direction:column;align-items:stretch;gap:5px;margin:8px 0 2px}
.of-salida{font-family:inherit;font-size:11.5px;font-weight:600;cursor:pointer;
  border:1px solid var(--ok);color:var(--ok);background:transparent;
  border-radius:20px;padding:4px 11px;line-height:1.4;text-align:center}
.of-salida:hover{background:var(--ok);color:#fff}
/* El pedido de cambios no es una salida feliz: va en ámbar. */
.of-salida[data-mover="revisada"]{border-color:var(--warn);color:var(--warn)}
.of-salida[data-mover="revisada"]:hover{background:var(--warn);color:#fff}
/* En la columna de costeo la acción es un enlace al presupuesto, no un
   movimiento del tablero: mismo botón, en el azul de la casa. */
a.of-salida{display:block;text-decoration:none;border-color:var(--navy2);color:var(--navy2)}
a.of-salida:hover{background:var(--navy2);color:#fff}

/* Bitácora del expediente: una línea por hecho, la más nueva abajo. */
.bitacora-lista{list-style:none;margin:0;padding:0;font-size:13px}
.bitacora-lista li{display:flex;gap:10px;align-items:baseline;padding:7px 0;
  border-bottom:1px dashed var(--border)}
.bitacora-lista li:last-child{border-bottom:0}
.bit-fecha{font-variant-numeric:tabular-nums;color:var(--muted);white-space:nowrap;min-width:78px}
.bit-ver{font-size:11px;font-weight:700;color:var(--accent);background:var(--surface2);
  border-radius:8px;padding:0 6px;white-space:nowrap}
.bit-txt{flex:1}
.bit-quien{color:var(--muted);font-size:12px;white-space:nowrap}
.bitacora-lista li.bit-revision .bit-txt{color:var(--accent)}
.bitacora-lista li.bit-ot .bit-txt{color:var(--ok)}

/* Aviso de cambios sin guardar */
.dlg{border:1px solid var(--border);border-radius:var(--radius);background:var(--card);color:var(--text);
  padding:22px 24px;max-width:440px;width:calc(100% - 32px);box-shadow:var(--shadow-lg)}
.dlg::backdrop{background:rgba(0,0,0,.45)}
.dlg h3{margin:0 0 8px;color:var(--heading);font-size:16px}
.dlg p{margin:0 0 18px;font-size:14px;color:var(--muted)}
.dlg-acciones{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}

/* Forms */
/* Grilla de 12 columnas. El campo normal ocupa 6 (media pantalla, igual que
   siempre); las clases w-* la achican para los datos cortos, así el número
   de la calle o un talle no se llevan medio formulario. 12 y no 2 columnas
   porque es el único múltiplo que da mitades, tercios y cuartos exactos. */
.form-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:16px}
.field{display:flex;flex-direction:column;gap:5px;font-size:13px;color:var(--muted);grid-column:span 6}
.field.full{grid-column:1 / -1}
.field.w-tercio{grid-column:span 4}
.field.w-cuarto{grid-column:span 3}
.field.w-mini{grid-column:span 2}
.field input,.field select,.field textarea{font-family:inherit;font-size:14px;color:var(--text);padding:8px 10px;border:1px solid var(--border);border-radius:7px;background:var(--input-bg)}
.field input[type=checkbox]{width:18px;height:18px}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--accent)}
.field input:disabled{background:var(--surface2);color:var(--muted);cursor:not-allowed}
.field>span:first-child{font-weight:500;color:var(--heading)}
.field-help{font-size:11.5px;color:var(--muted);line-height:1.35}

/* Formularios largos: cada sección es un bloque plegable con su propio avance,
   así una entidad de 40+ campos no se lee como una pared. Se usa <details>
   nativo (sin JS y sin handlers inline, que la CSP bloquea). Arrancan abiertas:
   un campo obligatorio dentro de una sección cerrada no se puede enfocar y el
   navegador no sabría dónde mostrar el mensaje de validación. */
.form-sec{border:1px solid var(--border);border-radius:10px;margin-bottom:14px;background:var(--surface2)}
.form-sec>summary{display:flex;align-items:center;gap:10px;padding:11px 14px;cursor:pointer;border-radius:10px;
  font-size:13px;font-weight:600;color:var(--heading);list-style:none;-webkit-user-select:none;user-select:none}
.form-sec>summary::-webkit-details-marker{display:none}
.form-sec>summary::after{content:'▾';margin-left:auto;color:var(--muted);font-size:12px;transition:transform var(--tr)}
.form-sec[open]>summary::after{transform:rotate(180deg)}
.form-sec>summary:hover{background:rgba(21,101,160,.07)}
.form-sec>summary:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.sec-n{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;flex:none;
  border-radius:50%;background:var(--navy2);color:#fff;font-size:11px;font-weight:700}
.sec-i{flex:none;color:var(--accent)}
.sec-i .ico{width:18px;height:18px;vertical-align:0}
.sec-t{flex:1}
.sec-c{font-weight:400;font-size:11.5px;color:var(--muted);background:var(--card);
  border:1px solid var(--border);border-radius:9px;padding:1px 8px}
.form-sec .form-grid{padding:14px;background:var(--card);border-top:1px solid var(--border);border-radius:0 0 10px 10px}
/* Para qué sirve el bloque. Va dentro del plegable, arriba de los campos:
   ahí se lee cuando hace falta y no estorba el resto del tiempo. */
.sec-ayuda{margin:0;padding:11px 14px 0;background:var(--card);border-top:1px solid var(--border);
  font-size:12px;line-height:1.45;color:var(--muted)}
.sec-ayuda + .form-grid{border-top:0;padding-top:12px}

/* Acción propia del bloque (ej. bajar la check list del proveedor). Va pegada
   al título y no contra el borde derecho: es lo que la ata al bloque que la
   ofrece. Por eso el título deja de estirarse y el contador pasa a ser el que
   empuja — sólo en las cabeceras con acción, para no mover el resto. */
summary.con-accion .sec-t{flex:0 1 auto}
summary.con-accion .sec-c{margin-left:auto}
.sec-accion{display:inline-flex;align-items:center;gap:6px;flex:none;
  border:1px solid var(--border);border-radius:7px;background:var(--card);color:var(--accent);
  padding:4px 10px;font-size:11.5px;font-weight:600;font-family:inherit;line-height:1.4;
  cursor:pointer;transition:background var(--tr),border-color var(--tr)}
.sec-accion .ico{width:15px;height:15px;vertical-align:0}
.sec-accion:hover{background:var(--surface2);border-color:var(--accent)}
.sec-accion:disabled{cursor:progress}
/* Apagada de entrada (sin IA en el servidor, o ficha sin guardar todavía): se
   muestra igual para que se sepa que la acción existe; el `title` dice qué
   falta para poder usarla. */
.sec-accion.is-off{color:var(--muted);cursor:not-allowed;background:transparent}
.sec-accion.is-cargando{color:var(--muted)}
.sec-accion.is-cargando .ico{animation:sec-late 1.1s ease-in-out infinite}
@keyframes sec-late{0%,100%{opacity:.35}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){.sec-accion.is-cargando .ico{animation:none}}
/* El resultado de la acción, dentro del plegable y arriba de todo: es donde
   está mirando quien apretó el botón. */
.sec-accion-aviso{margin:0;padding:10px 14px;background:var(--card);border-top:1px solid var(--border);
  font-size:12px;line-height:1.45;color:var(--muted)}
.sec-accion-aviso.ok{color:var(--ok)}
.sec-accion-aviso.error{color:var(--danger)}
.sec-accion-aviso + .sec-ayuda{border-top:0;padding-top:8px}
.sec-accion-aviso + .form-grid{border-top:0;padding-top:12px}

/* La barra de guardado queda a la vista aunque el formulario sea largo. */
.form-actions{display:flex;align-items:center;justify-content:flex-end;gap:10px;margin-top:18px;
  position:sticky;bottom:0;background:var(--card);padding:12px 0 2px;border-top:1px solid var(--border)}
.form-hint{margin-right:auto;font-size:12px}

/* Matriz de riesgo 5x5 clickeable. Los fondos son fijos (semáforo) con texto
   oscuro: se leen igual en tema claro y oscuro, como el resto de los badges.
   El primer bloque anula los estilos globales de `table` (ancho 100%, padding
   9px, th con fondo y versalitas), que si no estiran la grilla a todo lo ancho. */
.matriz{overflow-x:auto;padding-top:2px}
.mz-grid{border-collapse:separate;border-spacing:2px;width:auto}
.mz-grid th,.mz-grid td{border:0;padding:0;background:none;text-transform:none;letter-spacing:normal;vertical-align:middle}
.mz-wrap{display:flex;align-items:center;gap:4px}
.mz-axis-y{writing-mode:vertical-rl;transform:rotate(180deg);font-size:10px;color:var(--muted);letter-spacing:.05em;white-space:nowrap}
.mz-axis-x{margin:3px 0 0;font-size:10px;color:var(--muted);letter-spacing:.05em;text-align:center}
.mz-grid th[scope=row]{font-weight:400;font-size:10.5px;color:var(--muted);text-align:right;white-space:nowrap;padding-right:5px}
.mz-grid th .mz-num{margin-right:4px}
.mz-num{font-weight:700;color:var(--heading)}
.mz-foot td{font-size:10px;color:var(--muted);text-align:center;padding-top:3px;line-height:1.2}
.mz-foot .mz-num{display:block}
.mz-cell{display:block;width:46px;height:30px;border:1px solid rgba(16,24,40,.12);border-radius:5px;
  font-family:inherit;font-size:11.5px;font-weight:600;color:#1c2530;cursor:pointer;transition:filter var(--tr)}
.mz-cell:hover{filter:brightness(.94)}
.mz-cell.v-bajo{background:#cdeccf}
.mz-cell.v-moderado{background:#fbe7a2}
.mz-cell.v-alto{background:#f6c49a}
.mz-cell.v-critico{background:#efa79e}
.mz-cell.is-sel{outline:2px solid var(--accent);outline-offset:-1px;box-shadow:var(--shadow)}
.mz-result{margin:8px 0 0;font-size:12.5px;color:var(--muted)}

/* Auth */
.centered{display:flex;align-items:center;justify-content:center;min-height:100vh}
.auth{width:360px;max-width:90vw;text-align:center}
.auth h2{border:0;color:var(--navy);margin:14px 0}
.auth label{display:block;text-align:left;margin:10px 0;font-size:13px;color:var(--muted)}
.auth input{width:100%;padding:9px 11px;border:1px solid var(--border);border-radius:7px;font-size:14px;margin-top:4px}
.auth .btn{width:100%;margin-top:10px}

/* Chat / Asistente */
.chat{display:flex;flex-direction:column;gap:12px;margin:16px 0;max-height:55vh;overflow-y:auto;padding:4px}
.chat-empty{padding:16px;background:var(--surface2);border-radius:8px}
.msg{display:flex}
.msg.user{justify-content:flex-end}
.msg .bubble{max-width:78%;padding:10px 14px;border-radius:12px;font-size:14px;line-height:1.5}
.msg.user .bubble{background:var(--accent);color:#fff;border-bottom-right-radius:3px}
.msg.assistant .bubble{background:var(--surface2);color:var(--text);border-bottom-left-radius:3px}
.chat-input{display:flex;gap:10px;margin-top:8px}
.chat-input input{flex:1;padding:10px 12px;border:1px solid var(--border);border-radius:8px;font-size:14px}
.chat-input input:focus{outline:none;border-color:var(--accent)}

/* Misc */
.muted{color:var(--muted)} .small{font-size:12px}
.alert{padding:10px 14px;border-radius:7px;margin-bottom:14px;font-size:14px}
.alert.error{background:#fdecea;color:var(--danger);border:1px solid #f5c6c0}
.alert.success{background:#e7f6ec;color:var(--ok);border:1px solid #b6e0c4}
.alert.warn{background:#fdf4e3;color:#8a5d00;border:1px solid #ecd39a}
[data-theme="dark"] .alert.warn{background:#3a2f16;color:#f0cf88;border-color:#5c4a20}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .alert.warn{background:#3a2f16;color:#f0cf88;border-color:#5c4a20}}

/* Toolbar / búsqueda */
.toolbar{display:flex;gap:8px;margin-bottom:14px;flex-wrap:wrap}
.toolbar input[type=search]{flex:1;min-width:180px;padding:8px 11px;border:1px solid var(--border);border-radius:7px;font-size:14px;font-family:inherit;color:var(--text);background:var(--input-bg)}
.toolbar input[type=search]:focus{outline:none;border-color:var(--accent)}

/* Tablas: scroll horizontal en pantallas chicas + encabezados ordenables */
.table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
th a.th-sort{color:var(--heading);display:inline-flex;gap:2px;white-space:nowrap}
th a.th-sort:hover{color:var(--accent)}

/* Paginación */
.pager{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:14px;flex-wrap:wrap}
.pager .disabled{opacity:.45;pointer-events:none}

/* Accesibilidad: foco visible por teclado */
a:focus-visible,.btn:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* Topbar / hamburguesa */
.topbar-left{display:flex;align-items:center;gap:10px;min-width:0}
.topbar-left h1{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.menu-toggle{display:none;background:none;border:0;line-height:1;cursor:pointer;color:var(--heading);padding:2px 6px}
.menu-toggle .ico{width:22px;height:22px}
.sidebar-backdrop{display:none}

/* Responsive / móvil */
@media (max-width:860px){
  .menu-toggle{display:inline-block}
  .sidebar{position:fixed;top:0;left:0;bottom:0;width:250px;z-index:50;transform:translateX(-100%);transition:transform .25s ease;box-shadow:2px 0 14px rgba(0,0,0,.25)}
  .layout.nav-open .sidebar{transform:translateX(0)}
  .layout.nav-open .sidebar-backdrop{display:block;position:fixed;inset:0;background:rgba(0,0,0,.35);z-index:40}
  .content{padding:16px}
  /* En el celular la grilla pasa a 2 columnas: el campo normal ocupa las dos
     (ancho completo, como antes) y sólo los cortos se ponen de a pares —
     número y piso al lado, y no uno debajo del otro. */
  .form-grid{grid-template-columns:repeat(2,1fr)}
  .field{grid-column:span 2}
  /* w-tercio también va entero: «Localidad» en media pantalla de celular
     queda ilegible. Sólo los datos de dos o tres caracteres se aparean. */
  .field.w-tercio{grid-column:span 2}
  .field.w-cuarto,.field.w-mini{grid-column:span 1}
  .topbar{padding:12px 16px}
  .topbar h1{font-size:17px}
  .card{padding:16px}
  /* En pantalla chica la topbar no da para todo: se oculta el nombre del
     usuario (ya está en el menú) antes que los botones de acción. */
  .user{gap:8px}
  .user-nombre{display:none}
}

/* Botón de tema */
.theme-toggle{padding:6px 9px;line-height:1}

/* Toast de feedback (mensajes flash) */
.toast{position:fixed;top:16px;left:50%;transform:translate(-50%,-160%);background:var(--card);color:var(--text);border:1px solid var(--border);border-left:4px solid var(--accent);box-shadow:var(--shadow-lg);padding:12px 18px;border-radius:10px;font-size:14px;z-index:100;opacity:0;cursor:pointer;transition:transform .3s cubic-bezier(.16,1,.3,1),opacity .3s ease;max-width:92vw}
.toast.show{transform:translate(-50%,0);opacity:1}
.toast.success{border-left-color:var(--ok)}
.toast.error{border-left-color:var(--danger)}
.toast.warning{border-left-color:var(--warn)}

/* Auditoría de cambios: detalle legible campo por campo */
.cambio-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px;font-size:12px;line-height:1.5}
.cambio-campo{color:var(--muted)}
.cambio-antes{color:var(--muted);text-decoration:line-through}
.cambio-flecha{color:var(--muted)}
.cambio-despues{color:var(--heading)}
.cambio-mas summary{cursor:pointer;color:var(--accent);font-size:12px;margin-bottom:4px}

/* Campo de contraseña con botón para revelarla */
.input-reveal{position:relative;display:flex}
.input-reveal input{flex:1;min-width:0;padding-right:40px}
.reveal-btn{position:absolute;right:1px;top:1px;bottom:1px;width:38px;border:0;background:none;cursor:pointer;font-size:15px;line-height:1;color:var(--muted);border-radius:0 6px 6px 0}
.reveal-btn:hover{background:var(--surface2)}

/* Usuarios y control de acceso: matriz de permisos */
.is-hidden{display:none}
.checkbox-field{flex-direction:row;align-items:center;gap:9px}
.checkbox-field span{color:var(--text)}
.perm-group{border:1px solid var(--border);border-radius:var(--radius);padding:6px 14px 12px;margin-bottom:14px}
.perm-group legend{font-size:11px;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);padding:0 6px}
.perm-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:6px 18px}
.perm-item{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:6px 8px;border-radius:7px}
.perm-item:hover{background:var(--surface2)}
.perm-ver,.perm-edit{display:flex;align-items:center;gap:8px;font-size:14px;cursor:pointer;min-width:0}
.perm-ver span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.perm-edit{font-size:12px;color:var(--muted);white-space:nowrap;flex-shrink:0}
.perm-item input[type=checkbox]{width:17px;height:17px;flex-shrink:0;accent-color:var(--accent)}
@media (max-width:860px){ .perm-list{grid-template-columns:1fr} }

/* Transiciones suaves */
body{transition:background var(--tr),color var(--tr)}
.btn{transition:background var(--tr),border-color var(--tr),transform var(--tr)}
.btn:active{transform:translateY(1px)}
.btn-primary{box-shadow:var(--shadow)}

/* ===================================================================
   TABLERO DE FLUJO COMERCIAL (/flujo)
   Las columnas son las etapas de PR-COM-001 y las barras ámbar las
   compuertas. Usa los tokens de arriba: sin paleta propia.
   =================================================================== */
.board-wrap{overflow-x:auto;padding-bottom:10px;margin-bottom:20px}
.flujo-board{display:grid;gap:0 12px;align-items:start;min-width:1900px;
  grid-template-columns:repeat(7,minmax(206px,1fr)) 20px repeat(2,minmax(178px,.72fr))}
/* El tablero de ofertas calcula su grilla en la vista, desde las etapas que
   declara src/ofertas.js (ver views/ofertas.ejs): con el número de columnas
   equivocado, la fila de tarjetas se mete en los huecos sobrantes de la de
   encabezados y las tarjetas no aparecen debajo de su columna. Lo de acá es
   sólo el respaldo por si la vista no lo pasa. */
.of-board{min-width:1400px;
  grid-template-columns:repeat(6,minmax(218px,1fr)) 20px minmax(172px,.7fr)}
/* Flujo comercial: cuatro etapas y ninguna salida. */
.fc-board{min-width:900px;
  grid-template-columns:repeat(3,minmax(280px,1fr))}
.fb-gap{}

/* Cinta de etapas */
.fb-head{position:relative;padding:0 0 12px}
.fb-bar{height:3px;border-radius:2px;background:var(--navy2);margin-bottom:9px}
.fb-head.is-off .fb-bar{background:var(--border)}
.fb-title{display:flex;align-items:baseline;gap:8px}
.fb-name{font-size:11.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--heading)}
.fb-head.is-off .fb-name{color:var(--muted)}
.fb-count{margin-left:auto;font-size:11.5px;font-weight:700;color:var(--muted);
  background:var(--surface2);border-radius:999px;padding:1px 8px;font-variant-numeric:tabular-nums}
.fb-sub{font-size:10.5px;color:var(--muted);margin-top:3px;font-family:ui-monospace,Consolas,monospace}
.fb-who{font-size:10.5px;color:var(--accent);margin-top:2px}
.fb-gate{position:absolute;top:0;right:-7px;width:2px;height:100%;
  background:repeating-linear-gradient(to bottom,var(--warn) 0 5px,transparent 5px 10px)}
.fb-gate-tip{position:absolute;top:-1px;right:-7px;transform:translateX(50%);
  background:var(--card);border:1px solid var(--warn);color:var(--warn);border-radius:999px;
  width:17px;height:17px;line-height:15px;text-align:center;font-size:10px;font-weight:700;
  cursor:help;z-index:2}
.fb-gate-tip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* Columnas */
.fb-col{border-radius:var(--radius);min-height:110px;padding:4px 2px 40px;
  transition:background var(--tr),box-shadow var(--tr)}
.fb-col.drop-ok{background:color-mix(in srgb,var(--accent) 9%,transparent);
  box-shadow:inset 0 0 0 2px color-mix(in srgb,var(--accent) 40%,transparent)}
.fb-col.drop-back{background:color-mix(in srgb,var(--warn) 11%,transparent);
  box-shadow:inset 0 0 0 2px color-mix(in srgb,var(--warn) 45%,transparent)}
.fb-col.drop-no{background:color-mix(in srgb,var(--danger) 7%,transparent)}
.fb-empty{color:var(--muted);text-align:center;font-size:12px;padding:22px 0;opacity:.55;margin:0}

/* Swimlane */
.fb-lane{border:1px solid var(--border);border-radius:9px;background:var(--card);
  margin-bottom:10px;overflow:hidden}
.fb-lane-head{display:flex;align-items:center;gap:7px;width:100%;padding:7px 9px;
  background:none;border:0;cursor:pointer;text-align:left;color:var(--heading);font-family:inherit}
.fb-lane-head:hover{background:var(--surface2)}
.fb-chev{font-size:9px;color:var(--muted);transition:transform var(--tr)}
.fb-lane.is-closed .fb-chev{transform:rotate(-90deg)}
.fb-lane-name{font-size:12px;font-weight:700;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fb-lane-n{font-size:10.5px;font-weight:700;color:var(--muted);background:var(--surface2);
  border-radius:999px;padding:0 6px}
.fb-lane-body{display:flex;flex-direction:column;gap:7px;padding:0 7px 7px}
.fb-lane.is-closed .fb-lane-body{display:none}

/* Tarjeta de expediente */
.fb-exp{border:1px solid var(--border);border-left:3px solid var(--navy2);border-radius:8px;
  background:var(--card);padding:8px 10px;display:flex;flex-direction:column;gap:5px}
.fb-exp[draggable=true]{cursor:grab}
.fb-exp:hover{box-shadow:var(--shadow)}
.fb-exp.is-drag{opacity:.35}
.fb-exp.l-salvage-buceo{border-left-color:#2a8f8f}
.fb-exp.l-mil{border-left-color:#6b5ba8}
.fb-exp.is-off{border-left-color:var(--border);opacity:.75}
.fb-exp-top{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.fb-num{font-family:ui-monospace,Consolas,monospace;font-size:11px;font-weight:700;color:var(--heading)}
/* El titulo identifica el trabajo en la tarjeta; el alcance queda como
   contexto secundario debajo. */
.fb-titulo{font-size:13px;font-weight:600;color:var(--heading);line-height:1.3;margin:0 0 4px}
.fb-desc{font-size:12.5px;line-height:1.35;margin:0}
.fb-who-chip{font-size:10.5px;color:var(--accent);border-radius:5px;padding:1px 6px;
  background:color-mix(in srgb,var(--accent) 10%,transparent)}
.fb-flags{display:flex;flex-wrap:wrap;gap:4px}
.fb-flag{font-size:10.5px;font-weight:600;border-radius:5px;padding:1px 6px}
.fb-flag.f-danger{background:color-mix(in srgb,var(--danger) 13%,transparent);color:var(--danger)}
.fb-flag.f-warn{background:color-mix(in srgb,var(--warn) 16%,transparent);color:var(--warn)}
.fb-chain{display:flex;flex-wrap:wrap;gap:4px;align-items:center;font-family:ui-monospace,Consolas,monospace;
  font-size:10px;color:var(--muted);border-top:1px solid var(--border);padding-top:5px}
.fb-chain i{font-style:normal;opacity:.5}
.fb-chain .on{color:var(--accent);font-weight:700}
.fb-exp-foot{display:flex;justify-content:flex-end;align-items:center;gap:12px}

/* Menú "Mover a…" — el drag & drop de HTML5 no existe en táctil */
.fb-mover{position:relative}
.fb-mover summary{list-style:none;cursor:pointer;font-size:11px;color:var(--muted);
  border:1px solid var(--border);border-radius:6px;padding:2px 6px;display:inline-block}
.fb-mover summary::-webkit-details-marker{display:none}
.fb-mover summary:hover{border-color:var(--navy2);color:var(--heading)}
.fb-mover-menu{position:absolute;right:0;top:100%;margin-top:4px;z-index:12;min-width:190px;
  background:var(--card);border:1px solid var(--border);border-radius:9px;
  box-shadow:var(--shadow-lg);padding:5px;display:flex;flex-direction:column;gap:2px}
.fb-mover-menu button{background:none;border:0;text-align:left;font:inherit;font-size:12.5px;
  color:var(--text);padding:6px 9px;border-radius:6px;cursor:pointer}
.fb-mover-menu button:hover{background:var(--surface2)}
.fb-retorno{font-size:10px;color:var(--warn);font-weight:700}

/* Diálogo de transición */
.fb-dialog{border:1px solid var(--border);border-radius:var(--radius);background:var(--card);
  color:var(--text);box-shadow:var(--shadow-lg);padding:0;width:min(470px,92vw)}
/* Con secciones enteras adentro, el diálogo necesita ancho de formulario. */
.fb-dialog:has(.fb-flds.is-compacto){width:min(760px,94vw)}
.fb-dialog::backdrop{background:rgba(16,24,40,.45)}
.fb-dlg-head{padding:16px 20px 12px;border-bottom:1px solid var(--border)}
.fb-dlg-gate{font-size:10.5px;font-weight:700;letter-spacing:.7px;text-transform:uppercase;color:var(--warn)}
.fb-dlg-gate.is-back{color:var(--accent)}
.fb-dlg-head h3{font-size:16px;margin:3px 0 0;color:var(--heading)}
.fb-dlg-sub{font-size:12px;color:var(--muted);margin:5px 0 0}
.fb-dlg-body{padding:16px 20px;max-height:62vh;overflow-y:auto}
.fb-dlg-foot{padding:12px 20px 16px;display:flex;gap:8px;justify-content:flex-end;border-top:1px solid var(--border)}
/* Subventana de revisión: cuando la transición trae secciones enteras de
   la entidad, los campos se acomodan en dos columnas para que entren de
   una mirada. Los textos largos y el encabezado ocupan el ancho completo. */
.fb-flds.is-compacto{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}
.fb-flds.is-compacto .fb-fld.is-full{grid-column:1 / -1}
.fb-sec{grid-column:1 / -1;font-size:11px;font-weight:700;text-transform:uppercase;
  letter-spacing:.9px;color:var(--muted);border-bottom:1px solid var(--border);
  padding-bottom:5px;margin:14px 0 11px}
.fb-sec:first-child{margin-top:0}
.fb-fld{display:flex;flex-direction:column;gap:4px;margin-bottom:13px}
.fb-fld:last-child{margin-bottom:0}
.fb-fld label{font-size:12px;font-weight:600;color:var(--heading)}
.fb-fld input,.fb-fld select,.fb-fld textarea{border:1px solid var(--border);border-radius:7px;
  padding:7px 9px;font:inherit;font-size:13px;background:var(--card);color:var(--text);width:100%}
.fb-fld small{font-size:11px;color:var(--muted)}
.fb-fld.is-check label{font-weight:400;display:flex;gap:8px;align-items:center}
.fb-fld.is-check input{width:auto;accent-color:var(--accent)}
.fb-info{font-size:12px;color:var(--accent);background:color-mix(in srgb,var(--accent) 10%,transparent);
  border-radius:6px;padding:5px 9px;align-self:flex-start}

@media (max-width:860px){ .flujo-board{min-width:1500px} .of-board{min-width:1340px} .fc-board{min-width:840px} }

/* El tablero necesita todo el ancho: .content está limitado a 1200px para que
   el texto de las demás pantallas no quede en líneas largas, pero un kanban de
   nueve columnas ahí adentro obliga a scrollear de más. */
.content:has(.flujo-board){max-width:none}

/* Campos condicionales: sólo se muestran si otro campo tiene cierto valor
   (ej. el motivo de la pérdida, que sólo aplica a un No Go). */
.field.is-oculto{display:none}

/* =================================================================
   ADJUNTOS DE UN REGISTRO (certificados de calibración y demás
   evidencia documentada).

   La miniatura manda: en una ficha de equipo lo que se busca es
   reconocer el certificado de un vistazo, no leer un nombre de
   archivo. Por eso cada ítem es imagen + datos, y no un renglón.
   ================================================================= */
.adjuntos .adj-body{padding:14px;background:var(--card);border-top:1px solid var(--border);border-radius:0 0 10px 10px}
.adj-lista{list-style:none;margin:0 0 16px;padding:0;display:grid;
  grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}
.adj-item{display:flex;gap:11px;border:1px solid var(--border);border-radius:9px;
  padding:9px;background:var(--surface2)}
/* Alto fijo: con certificados apaisados y verticales mezclados, si la
   miniatura manda el alto la grilla queda dentada. */
.adj-vista{flex-shrink:0;width:74px;height:88px;border-radius:7px;overflow:hidden;
  background:var(--card);border:1px solid var(--border);
  display:flex;align-items:center;justify-content:center}
.adj-vista img{width:100%;height:100%;object-fit:cover}
.adj-vista:hover{border-color:var(--accent)}
.adj-icono{display:inline-flex}
.adj-icono .ico{width:30px;height:30px;color:var(--muted)}
.adj-datos{display:flex;flex-direction:column;gap:2px;min-width:0;font-size:12px}
.adj-titulo{color:var(--heading);font-size:13px;overflow-wrap:anywhere}
.adj-ultimo{background:#e7f6ec;color:#1b7a3d;font-weight:600;font-size:10.5px;
  text-transform:uppercase;letter-spacing:.5px;align-self:flex-start;padding:1px 7px}
:root[data-theme="dark"] .adj-ultimo{background:rgba(66,192,108,.16);color:var(--ok)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .adj-ultimo{background:rgba(66,192,108,.16);color:var(--ok)}}
.adj-acciones{display:flex;align-items:center;gap:10px;margin-top:4px;font-size:12px}
.adj-acciones form{display:inline}
.adj-alta{font-size:11px}
/* Acción escrita dentro de una tarjeta: se lee como un enlace, no como un
   botón, para que "Eliminar" no compita con el resto de la ficha. */
.btn-link{background:none;border:0;padding:0;font:inherit;font-size:12px;
  color:var(--accent);cursor:pointer;text-decoration:none}
.btn-link:hover{text-decoration:underline}
.btn-link.danger{color:var(--danger)}
/* Título de un campo que no puede envolverse en <label> (el de archivos):
   se ve igual que el <span> de los demás. */
.field>.field-lbl{font-weight:500;color:var(--heading)}
.adj-alta-form{border-top:1px dashed var(--border);padding-top:14px}
/* La grilla ya vive dentro del cuerpo de la sección: no repite el fondo, el
   borde ni el padding que .form-sec .form-grid le pone al formulario. */
.adj-alta-form .form-grid{padding:0;background:none;border-top:0;border-radius:0}
/* La barra de guardado del registro queda pegada abajo; la de subir un
   archivo no: es una acción secundaria dentro de la sección. */
.adj-alta-form .form-actions{position:static;margin-top:12px;border:0;padding:0}
.adj-aviso{margin:0 0 14px}

/* Columna de archivos en el listado: dice si el registro tiene la
   evidencia cargada, sin abrirlo. */
td.adj-col,th.adj-col{width:1%;white-space:nowrap;text-align:center}
.adj-chip{background:var(--surface2);border:1px solid var(--border);gap:4px;
  border-radius:10px;padding:2px 8px;font-size:12px;color:var(--heading)}

/* =================================================================
   CARGA ASISTIDA POR IA

   Un solo color —el ámbar— para todo lo que propuso la IA y todavía no
   guardó nadie: el panel, los campos tocados y el resumen. Mientras
   haya amarillo en pantalla, hay algo sin revisar.
   ================================================================= */
:root{--ia-bg:#fffbea;--ia-line:#e6c757;--ia-txt:#8a5d00}
:root[data-theme="dark"]{--ia-bg:#2a2413;--ia-line:#7a6320;--ia-txt:#e6c98a}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){--ia-bg:#2a2413;--ia-line:#7a6320;--ia-txt:#e6c98a}
}

.ia-panel{border:1px dashed var(--ia-line);border-radius:10px;background:var(--ia-bg);margin-bottom:14px}
.ia-panel>summary{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:10px 14px;
  cursor:pointer;border-radius:10px;font-size:14px;color:var(--ia-txt);font-weight:600}
.ia-panel>summary::-webkit-details-marker{display:none}
.ia-panel>summary::after{content:'▾';margin-left:auto;font-size:12px;transition:transform var(--tr)}
.ia-panel[open]>summary::after{transform:rotate(180deg)}
.ia-panel>summary small{font-weight:400}
.ia-panel>summary:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.ia-ico{color:var(--ia-line)}
.ia-body{padding:0 14px 14px;display:flex;flex-direction:column;gap:12px}
.ia-body p{margin:0}
.ia-adj{border:1px solid var(--ia-line);border-radius:8px;padding:8px 12px 10px;margin:0}
.ia-adj legend{font-size:12px;color:var(--ia-txt);padding:0 5px}
.ia-adj-item{display:flex;align-items:center;gap:8px;font-size:13px;padding:3px 0;color:var(--text)}
.ia-adj-item input{width:16px;height:16px}
.ia-acciones{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.ia-estado{font-size:13px;color:var(--muted)}
.ia-estado.is-error{color:var(--danger)}
.ia-estado.is-cargando::before{content:'⏳ '}

/* Campo tocado por la IA: la marca ámbar dura hasta que se guarda o se
   deshace. Es la señal de "esto todavía no lo revisó nadie". */
.field.is-ia{background:var(--ia-bg);border-left:3px solid var(--ia-line);
  padding:6px 8px;margin:-6px -8px;border-radius:6px}
.field.is-ia>span:first-child::after{content:' ✨';font-size:11px}

/* Qué propuso y de dónde lo sacó. El borde izquierdo de cada ítem es la
   confianza: verde si está literal en la fuente, ámbar si se dedujo,
   rojo si es una conjetura que hay que mirar sí o sí. */
.ia-resumen{border:1px solid var(--ia-line);border-left:3px solid var(--ia-line);
  border-radius:8px;background:var(--ia-bg);padding:12px 14px;margin-bottom:14px}
.ia-resumen-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.ia-resumen-head strong{color:var(--ia-txt);font-size:14px}
.ia-lista{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-direction:column;gap:7px}
.ia-item{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;font-size:13px;
  border-left:3px solid var(--ok);padding-left:9px;color:var(--text)}
.ia-item.conf-media{border-left-color:var(--warn)}
.ia-item.conf-baja{border-left-color:var(--danger)}
.ia-item.is-descarte{border-left-color:var(--border);color:var(--muted);font-size:12px}
.ia-item.is-pisa strong::after{content:' ⚠';color:var(--warn)}
.ia-val{background:var(--card);border:1px solid var(--border);border-radius:5px;padding:0 6px;font-size:12.5px}
.ia-item small{flex:1 1 100%;font-size:11.5px}
.ia-nota{margin:10px 0 0;white-space:pre-line}
.ia-redactar{align-self:flex-start;margin-top:2px}

/* Aviso del campo «combo»: qué va a pasar con el tercero que se escribió.
   Tres estados — ya existe, se parece a otros, es nuevo — con el color
   diciendo cuál es cuál antes de leer el texto. */
.combo-aviso{margin-top:6px;font-size:12.5px;display:flex;flex-wrap:wrap;gap:6px;align-items:center;
  border-left:3px solid var(--border);padding:5px 0 5px 9px;color:var(--muted)}
.combo-aviso.ok{border-left-color:var(--ok);color:var(--ok)}
.combo-aviso.ojo{border-left-color:var(--warn)}
.combo-aviso.nuevo{border-left-color:var(--navy2)}
.combo-opcion{font-family:inherit;font-size:12px;cursor:pointer;background:var(--card);
  border:1px solid var(--border);border-radius:14px;padding:3px 11px;color:var(--text)}
.combo-opcion:hover{background:var(--navy2);border-color:var(--navy2);color:#fff}

/* ===================================================================
   LA OT COMO PROYECTO (/ot/:id/proyecto)
   Gantt, actividades, carga por persona y costo real contra el
   presupuesto. Usa los tokens de arriba: sin paleta propia.
   =================================================================== */
.pr-cab{display:flex;flex-wrap:wrap;gap:14px;align-items:baseline;justify-content:space-between}
.pr-cab .num{font-size:20px;font-weight:700;color:var(--heading)}
.pr-cab .tit{color:var(--muted)}

/* Pestañas. No son links: alternan secciones ya renderizadas, así pasar
   de Gantt a Costos no recarga ni pierde el scroll. */
.pr-tabs{display:flex;gap:2px;flex-wrap:wrap;align-items:flex-end;
  border-bottom:2px solid var(--border);margin-bottom:18px}
.pr-tabs button{background:transparent;border:0;border-bottom:2px solid transparent;margin-bottom:-2px;
  padding:9px 15px;font-size:13.5px;color:var(--muted);cursor:pointer;font-family:inherit;
  transition:color var(--tr),border-color var(--tr)}
.pr-tabs button:hover{color:var(--text)}
.pr-tabs button.on{color:var(--accent);border-bottom-color:var(--accent);font-weight:600}
.pr-panel[hidden]{display:none}
/* Cuántos registros de ejecución tienen algo vencido. Va en la solapa para
   que se vea sin abrirla: un WPS vencido descubierto en la auditoría ya es
   tarde. */
.pr-pin{display:inline-block;margin-left:6px;background:var(--danger);color:#fff;font-weight:700;
  border-radius:9px;padding:0 6px;font-size:11px;line-height:17px;vertical-align:1px}
.reg-alerta>td{background:#fdf4e3}
[data-theme="dark"] .reg-alerta>td{background:#3a2f16}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .reg-alerta>td{background:#3a2f16}}
.reg-aviso{display:flex;align-items:center;gap:5px;margin-top:3px;font-size:12px;color:#8a5d00}
.reg-aviso .ico{width:14px;height:14px;flex:none}
[data-theme="dark"] .reg-aviso{color:#f0cf88}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .reg-aviso{color:#f0cf88}}

/* --- Gantt --- */
.gt-wrap{display:flex;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;background:var(--card)}
.gt-lbl{flex:0 0 290px;border-right:2px solid var(--border);background:var(--card);z-index:2}
.gt-scroll{overflow-x:auto;flex:1}
.gt-head{height:46px;border-bottom:1px solid var(--border);background:var(--surface2)}
.gt-lbl .gt-head{display:flex;align-items:flex-end;padding:0 12px 7px;font-size:11px;
  text-transform:uppercase;letter-spacing:.5px;color:var(--muted);font-weight:700}
.gt-meses{display:flex;height:22px;border-bottom:1px solid var(--border)}
.gt-mes{font-size:11px;font-weight:700;color:var(--heading);padding-left:7px;
  border-right:1px solid var(--border);line-height:22px;overflow:hidden;white-space:nowrap}
/* El eje ocupa el ancho de la ventana (100 %) y sólo lo pasa cuando el
   trabajo no entra con el zoom elegido; ahí aparece el scroll. */
.gt-eje{min-width:100%}
.gt-dias{display:flex;height:24px}
/* Sin ancho fijo: los días se reparten el eje en partes iguales, así el
   dibujo se reacomoda solo cuando cambia el tamaño de la ventana. */
.gt-dia{flex:1 1 0;min-width:0;text-align:center;font-size:10px;line-height:24px;
  color:var(--muted);font-variant-numeric:tabular-nums;overflow:hidden}
.gt-dia.finde{background:var(--surface2);color:var(--border)}
.gt-fila-lbl{display:flex;align-items:center;gap:8px;padding:0 12px;border-bottom:1px solid var(--border);
  font-size:13px;overflow:hidden}
.gt-fila-lbl .cod{font-size:11px;font-weight:700;color:var(--muted);flex-shrink:0;font-variant-numeric:tabular-nums}
.gt-fila-lbl .nom{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gt-cuerpo{position:relative}
.gt-fila{position:relative;border-bottom:1px solid var(--border)}
.gt-finde{position:absolute;top:0;bottom:0;background:var(--surface2);pointer-events:none}
.gt-hoy{position:absolute;top:0;bottom:0;width:2px;background:var(--danger);z-index:4;pointer-events:none}
.gt-hoy::after{content:'hoy';position:absolute;top:-19px;left:-11px;font-size:10px;font-weight:700;
  color:var(--danger);background:var(--card);padding:0 3px;border-radius:3px}
.gt-barra{position:absolute;top:9px;height:20px;border-radius:5px;z-index:3;display:flex;align-items:center;
  overflow:hidden;box-shadow:0 1px 2px rgba(16,24,40,.18)}
.gt-barra .pct{font-size:10px;font-weight:700;color:#fff;padding-left:7px;white-space:nowrap;
  text-shadow:0 1px 1px rgba(0,0,0,.35)}
.gt-barra .relleno{position:absolute;left:0;top:0;bottom:0;background:rgba(255,255,255,.28)}
.gt-barra.e-fin{background:var(--ok)}
.gt-barra.e-curso{background:var(--navy2)}
.gt-barra.e-pausa{background:var(--warn)}
.gt-barra.e-pend{background:var(--border)}
.gt-barra.e-pend .pct{color:var(--muted);text-shadow:none}
.gt-barra.e-cancel{background:repeating-linear-gradient(45deg,var(--border) 0 6px,transparent 6px 12px);
  border:1px solid var(--border)}
.gt-barra.atraso{outline:2px solid var(--danger)}
.gt-fantasma{position:absolute;top:7px;height:24px;border:1px dashed var(--muted);border-radius:6px;
  opacity:.6;z-index:2;pointer-events:none}
.gt-flechas{position:absolute;top:0;left:0;width:100%;pointer-events:none;z-index:1;overflow:visible}
/* La punta va fuera del SVG: adentro, el estirado horizontal del eje la
   dejaría como una aguja o como un abanico según el zoom. */
.gt-punta{position:absolute;width:0;height:0;margin:-4px 0 0 -6px;z-index:1;pointer-events:none;
  border-top:4px solid transparent;border-bottom:4px solid transparent;
  border-left:6px solid var(--muted);opacity:.7}
.gt-flechas path{fill:none;stroke:var(--muted);stroke-width:1.3;opacity:.7}
/* Capa de arrastre: transparente sobre el tramo PREVISTO de la actividad.
   Va aparte de la barra para no ensuciar lo que se ve, y para existir
   igual cuando el plan quedó atrás en fantasma. */
.gt-drag{position:absolute;top:5px;height:28px;z-index:5;cursor:grab;border-radius:6px;
  border:1px solid transparent;transition:border-color var(--tr),background var(--tr)}
.gt-drag:hover{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 10%,transparent)}
.gt-drag.arrastrando{cursor:grabbing;border-color:var(--accent);
  background:color-mix(in srgb,var(--accent) 18%,transparent)}
.gt-grip{position:absolute;top:0;bottom:0;width:9px;cursor:ew-resize;border-radius:5px}
.gt-grip.iz{left:-2px} .gt-grip.de{right:-2px}
.gt-drag:hover .gt-grip{background:var(--accent);opacity:.55}
.gt-vacio{padding:26px;color:var(--muted);font-size:13.5px}
.gt-leyenda{display:flex;flex-wrap:wrap;gap:15px;font-size:12px;color:var(--muted);margin:12px 0 0}
.gt-leyenda i{display:inline-block;width:20px;height:10px;border-radius:3px;vertical-align:-1px;margin-right:5px}

/* Dónde se hace: el astillero y el buque se planifican distinto, y el
   cliente los nombró como dos mundos separados. */
.pr-lugar{flex-shrink:0;font-size:10px;border-radius:9px;padding:1px 7px;font-weight:600;white-space:nowrap}
.pr-lugar.astillero{background:rgba(46,90,140,.14);color:var(--navy2)}
.pr-lugar.bordo{background:rgba(184,134,11,.16);color:var(--warn)}
.pr-lugar.externo{background:var(--surface2);color:var(--muted)}

/* --- Actividad desplegable: la lista se lee de un vistazo y se abre
       sólo la que se va a tocar. --- */
.pr-act{border:1px solid var(--border);border-radius:var(--radius);margin-bottom:9px;background:var(--card)}
.pr-act>summary{list-style:none;cursor:pointer;padding:11px 14px;display:flex;gap:10px;
  align-items:center;flex-wrap:wrap}
.pr-act>summary::-webkit-details-marker{display:none}
.pr-act>summary::before{content:'▸';color:var(--muted);font-size:12px;flex-shrink:0}
.pr-act[open]>summary::before{content:'▾'}
.pr-act[open]>summary{border-bottom:1px solid var(--border);background:var(--surface2)}
.pr-act .a-cod{font-size:11.5px;font-weight:700;color:var(--muted);font-variant-numeric:tabular-nums}
.pr-act .a-nom{font-weight:600;flex:1 1 190px}
.pr-act .a-fechas{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}
.pr-act .a-horas{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}
.pr-act .a-atraso{font-size:11.5px;font-weight:700;color:var(--danger);white-space:nowrap}
.pr-cuerpo{padding:14px}
.pr-sub{font-size:11.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);
  font-weight:700;margin:16px 0 7px}
.pr-sub:first-child{margin-top:0}

/* Rejilla de campos reutilizada por los formularios del proyecto. */
.pr-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;align-items:end}
.pr-grid label{display:block;font-size:12px;color:var(--muted);margin-bottom:4px}
.pr-grid input,.pr-grid select,.pr-grid textarea{width:100%;padding:7px 9px;font-size:13.5px;
  border:1px solid var(--border);border-radius:7px;background:var(--input-bg);color:var(--text);font-family:inherit}
.pr-grid .full{grid-column:1/-1}
.pr-acciones{display:flex;gap:9px;flex-wrap:wrap;align-items:center;margin-top:13px}

.pr-mini{width:100%;font-size:13px;margin-top:4px}
.pr-mini td,.pr-mini th{padding:6px 9px}
.pr-nueva{background:var(--surface2);border:1px dashed var(--navy2);border-radius:var(--radius);
  padding:14px 16px;margin-top:16px}
.pr-nueva h3{margin:0 0 11px;font-size:14px;color:var(--heading)}

/* Doble compromiso de un recurso. El ámbar es «mirá esto» y el rojo es
   «alguien se queda sin la máquina»: los dos colores ya significan eso en
   el resto del SIG, así que no se inventa una paleta nueva para el aviso.
   El fondo va con color-mix sobre la superficie de la tarjeta para que el
   cartel no quede blanco en modo oscuro. */
.pr-alerta{border:1px solid var(--warn);border-left-width:4px;border-radius:var(--radius);
  background:color-mix(in srgb, var(--warn) 9%, var(--card));
  padding:11px 14px;margin-bottom:16px;font-size:13.5px;line-height:1.5}
.pr-alerta.grave{border-color:var(--danger);background:color-mix(in srgb, var(--danger) 9%, var(--card))}
.pr-alerta b{color:var(--heading)}
.pr-alerta-pie{margin-top:6px;font-size:12px;color:var(--muted)}
.pr-cruce{font-size:12px;color:var(--warn);font-weight:600;margin-top:3px}
.pr-cruce.choque{color:var(--danger)}
/* El punto de la solapa: se ve de reojo y no mueve el ancho del botón. */
.pr-pin{color:var(--warn);font-size:11px;margin-left:5px;vertical-align:top;line-height:1}
.pr-pin.grave{color:var(--danger)}
/* Marca de que el recurso es una unidad de la flota y no un texto: es lo
   que explica por qué ESE renglón se controla por patente y los otros no. */
.pr-flota{font-size:10px;text-transform:uppercase;letter-spacing:.5px;font-weight:700;
  color:var(--accent);border:1px solid var(--accent);border-radius:4px;padding:0 4px;
  margin-left:6px;vertical-align:middle}
.pr-ayuda{font-size:12px;color:var(--muted);margin-top:5px}

/* --- Costos --- */
.pr-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(185px,1fr));gap:13px;margin-bottom:18px}
.pr-kpi{background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);padding:13px 15px}
.pr-kpi .lbl{font-size:11.5px;color:var(--muted);text-transform:uppercase;letter-spacing:.4px}
.pr-kpi .val{font-size:23px;font-weight:700;color:var(--heading);font-variant-numeric:tabular-nums;
  margin-top:3px;line-height:1.2}
.pr-kpi .pie{font-size:11.5px;color:var(--muted);margin-top:3px}
.pr-kpi.mal .val{color:var(--danger)} .pr-kpi.bien .val{color:var(--ok)} .pr-kpi.ojo .val{color:var(--warn)}
.pr-medidor{height:8px;border-radius:5px;background:var(--border);overflow:hidden;margin-top:7px}
.pr-medidor span{display:block;height:100%;background:var(--navy2)}
.pr-medidor.mal span{background:var(--danger)}
.pr-medidor.bien span{background:var(--ok)}
.pr-aviso{background:rgba(184,134,11,.12);border:1px solid var(--warn);border-radius:var(--radius);
  padding:12px 15px;margin-bottom:16px;font-size:13.5px}

@media (max-width:900px){ .gt-lbl{flex-basis:180px} }

/* -----------------------------------------------------------------
   ETAPAS DEL PROYECTO, ASIGNACIONES Y COSTOS CARGADOS A MANO
   (feedback del cliente, 19-08-2026)
   ----------------------------------------------------------------- */
/* El administrador de etapas vive arriba de las actividades y arranca
   plegado cuando ya hay etapas: se define una vez y después estorba. */
.pr-etapas{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface2);margin-bottom:16px}
.pr-etapas>summary{list-style:none;cursor:pointer;padding:10px 14px;display:flex;align-items:center;gap:10px;
  font-size:13px;font-weight:600;color:var(--heading)}
.pr-etapas>summary::-webkit-details-marker{display:none}
.pr-etapas>summary::before{content:'▸';color:var(--muted);font-size:12px}
.pr-etapas[open]>summary::before{content:'▾'}
.pe-tit{flex:1}
.pe-n{font-weight:400;font-size:11.5px;color:var(--muted);background:var(--card);
  border:1px solid var(--border);border-radius:9px;padding:1px 8px}
.pe-cuerpo{padding:12px 14px 14px;background:var(--card);border-top:1px solid var(--border);
  border-radius:0 0 var(--radius) var(--radius)}
.pe-form{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.pe-form input{padding:6px 8px;border:1px solid var(--border);border-radius:6px;
  background:var(--input-bg);color:var(--text);font-family:inherit;font-size:13px}
.pe-form input[name=descripcion]{flex:1;min-width:140px}
.pe-alta{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:12px;
  padding-top:12px;border-top:1px dashed var(--border)}
.pe-alta label{font-size:12px;color:var(--muted);font-weight:600}
.pe-alta input{padding:7px 9px;border:1px solid var(--border);border-radius:7px;
  background:var(--input-bg);color:var(--text);font-family:inherit;font-size:13.5px}
.pe-alta input[name=descripcion]{flex:1;min-width:160px}

/* Cabecera de cada bloque de actividades. Es la línea que hace que el
   proyecto se lea por etapas y no como una lista de treinta tareas. */
.pr-etapa-cab{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  margin:20px 0 8px;padding:7px 12px;border-left:3px solid var(--accent);
  background:var(--surface2);border-radius:0 7px 7px 0}
.pr-etapa-cab .pe-nom{font-weight:700;color:var(--heading);font-size:14px}
.pr-etapa-cab .pe-meta{font-size:12px;color:var(--muted)}
.pe-barra{width:90px;height:6px;border-radius:3px;background:var(--border);overflow:hidden;margin-left:auto}
.pe-barra i{display:block;height:100%;background:var(--ok)}
.pe-pct{font-size:12px;font-weight:700;color:var(--muted);font-variant-numeric:tabular-nums}
.pe-desc{margin:0 0 8px 15px;font-size:12.5px;color:var(--muted)}
.pe-vacia{margin:0 0 10px 15px;font-size:13px;color:var(--muted)}

/* En el Gantt la etapa se marca en la primera fila de su grupo. Va como
   borde y etiqueta dentro de la fila: una fila extra desalinearía las
   etiquetas respecto de las barras. */
/* La etapa es un renglón propio, del mismo alto de los dos lados del
   cronograma (la altura sale de src/proyecto.js, no del CSS: si la
   pusiera acá, el lado de las barras no se enteraría). Así los códigos y
   los nombres de las actividades siguen alineados en columna. */
.gt-banda{display:flex;align-items:center;padding:0 12px;gap:8px;
  font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;
  color:var(--accent);background:var(--surface2);
  border-bottom:1px solid var(--border);border-top:1px solid var(--border);
  overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.gt-banda-barras{background:var(--surface2);border-bottom:1px solid var(--border);
  border-top:1px solid var(--border)}

/* Barra de arriba del cronograma: el zoom a la izquierda y la ayuda del
   arrastre a la derecha, en una sola línea para no comerle alto al
   dibujo, que es lo que se vino a mirar. */
/* Selector de fechas a la vista. Va en la fila de las pestañas, pegado a
   la derecha: es el control de la vista, no del contenido. */
.gt-zoom{display:flex;align-items:center;gap:6px;flex:none;margin-left:auto;padding-bottom:6px}
.gt-zoom[hidden]{display:none}
.gt-zoom .btn{padding:4px 11px;font-size:14px;line-height:1.1;min-width:34px}
.gt-zoom .btn.disabled{opacity:.4;pointer-events:none}
.gz-lbl{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);font-weight:700}
.gz-nivel{font-size:12px;font-weight:600;color:var(--heading);font-variant-numeric:tabular-nums;
  min-width:58px;text-align:center}
.gt-ayuda{margin:0 0 12px;font-size:12.5px;color:var(--muted)}

/* Actividades asignadas a una persona, con su «quitar» al lado. */
.pr-asigs{display:flex;flex-wrap:wrap;gap:5px}
.pr-chip{display:inline-flex;align-items:center;gap:4px;background:var(--surface2);
  border:1px solid var(--border);border-radius:11px;padding:2px 4px 2px 9px;font-size:12px}
.pr-chip form{display:inline-flex}
.pr-chip-x{border:0;background:none;cursor:pointer;color:var(--muted);font-size:15px;line-height:1;
  padding:0 4px;border-radius:50%;font-family:inherit}
.pr-chip-x:hover{background:var(--danger);color:#fff}

/* «De dónde sale cada número»: la mitad de los costos no se cargan, se
   calculan, y sin decirlo se busca un formulario que no existe. */
.pr-deonde{margin:0 0 16px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface2)}
.pr-deonde>summary{cursor:pointer;padding:9px 13px;font-size:13px;font-weight:600;color:var(--heading)}
.pr-deonde ul{margin:0;padding:0 16px 12px 32px;font-size:12.5px;color:var(--muted);line-height:1.6}

.pr-costos input[type=number]{width:110px;padding:5px 7px;border:1px solid var(--border);border-radius:6px;
  background:var(--input-bg);color:var(--text);font-family:inherit;font-size:13px;text-align:right}

/* =====================================================================
   Asistentes de una capacitación (RG-RRH-005).

   Se pasa lista sobre la tabla misma: cada renglón es su propio form y
   se guarda solo. Por eso los controles van chicos y sin bordes fuertes
   — la fila tiene que seguir leyéndose como una fila, no como ocho
   formularios apilados. En el celular la tabla scrollea (.table-wrap),
   que es como se usa parada al lado del aula.
   ===================================================================== */
.asis-cab{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:6px 0 10px}
.asis-kpi{background:var(--surface2);border:1px solid var(--border);border-radius:11px;
  padding:3px 10px;font-size:12px;color:var(--muted)}
.asis-kpi b{color:var(--heading);font-size:13px}
.asis-kpi.ok b{color:var(--ok)}
.asis-kpi.alerta b{color:var(--warn)}
.asis-cab .btn{margin-left:auto}
.asis-tabla td{vertical-align:middle}
.asis-tabla select,.asis-tabla input[type=text],.asis-tabla input[type=number]{
  padding:4px 6px;border:1px solid var(--border);border-radius:6px;background:var(--input-bg);
  color:var(--text);font-family:inherit;font-size:12.5px;max-width:100%}
.asis-tabla .asis-nota{width:70px;text-align:right}
.asis-tabla .asis-firmo{text-align:center}
.asis-tabla .row-actions{display:flex;gap:4px;justify-content:flex-end}
/* Presente y ausente se tienen que distinguir de un vistazo: es lo único
   que se mira cuando la lista tiene treinta renglones. */
.asis-tabla tr.asis-si td:first-child{box-shadow:inset 3px 0 0 var(--ok)}
.asis-tabla tr.asis-no td:first-child{box-shadow:inset 3px 0 0 var(--danger)}
.badge.asis-ext{background:#fff4e0;color:#8a6508;margin-left:5px}
.asis-convocar{display:flex;flex-wrap:wrap;align-items:flex-end;gap:10px;margin-top:14px;
  padding:10px 12px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface2)}
.asis-convocar .field{flex:1 1 260px;margin:0}
.asis-alta{margin-top:12px}

/* A quién le llega la invitación. La dirección es un dato de trabajo, no
   un adorno: la columna es angosta pero el campo entra entero. */
.asis-tabla .asis-mail input{width:100%;min-width:150px}
.asis-sinmail{font-size:12px;color:var(--warn);white-space:nowrap}
/* El renglón que dice cuántos se enteran y cuántos no. Va pegado a los
   contadores, arriba de la tabla, porque se lee ANTES de mandar el mail. */
.asis-aviso{display:flex;align-items:flex-start;gap:7px;margin:0 0 10px;line-height:1.45}
.asis-aviso svg{flex:none;margin-top:2px}
/* Un botón que todavía no se puede usar (agendar sin fecha): se ve, se
   entiende por qué con el title, y no lleva a una pantalla de error. */
.btn.disabled{opacity:.45;pointer-events:none}

/* Estado y eficacia de una capacitación, con el mismo semáforo del resto
   del SIG: rojo = no sirvió, ámbar = a medias, verde = cerrado. */
.badge.v-no-eficaz,.badge.v-cancelada{background:#fdecea;color:#c0392b;font-weight:600}
.badge.v-parcialmente-eficaz,.badge.v-reprogramada{background:#fff4e0;color:#8a6508;font-weight:600}
.badge.v-eficaz,.badge.v-realizada{background:#e7f6ec;color:#1b7a3d}
.badge.v-programada{background:var(--surface2);color:var(--muted)}
/* =====================================================================
   ATS — Análisis de Trabajo Seguro (pestaña Riesgo de la OT).

   El color aparece una sola vez y siempre significa lo mismo: el NIVEL
   de riesgo residual. Si el estado del documento, los avisos y las
   etiquetas compitieran por el mismo rojo, el rojo dejaría de querer
   decir «esto puede lastimar a alguien».
   ===================================================================== */

/* Punto en la pestaña: el análisis no está terminado. Se ve sin entrar. */
.pr-punto{color:var(--warn);font-size:18px;line-height:0;margin-left:5px;vertical-align:middle}

/* Ayuda debajo de un campo. La misma idea que el `help` del CRUD. */
.pr-ayuda{display:block;margin-top:3px;font-size:11.5px;color:var(--muted);line-height:1.4}
label.chk{display:flex;align-items:center;gap:7px;font-size:13px;cursor:pointer;margin-top:22px}
label.chk input{margin:0}

.ats-vacio{text-align:center;padding:28px 20px;border:1px dashed var(--border);border-radius:var(--radius)}
.ats-vacio h3{margin:0 0 10px;color:var(--heading);font-size:16px}
.ats-vacio p{margin:0 auto 12px;max-width:62ch;font-size:13.5px;line-height:1.6;color:var(--text)}

.ats-cab{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;
  padding-bottom:12px;margin-bottom:12px;border-bottom:1px solid var(--border)}
.ats-cab .num{font-weight:700;color:var(--heading);font-size:15px;margin-right:8px}
.ats-estado.e-ok{background:rgba(27,122,61,.12);color:var(--ok)}
.ats-estado.e-no{background:rgba(192,57,43,.12);color:var(--danger)}
.ats-estado.e-pend{background:rgba(184,134,11,.14);color:var(--warn)}

/* El nivel de riesgo. Único lugar donde el color es semántico. */
.ats-nivel{display:inline-block;border-radius:10px;padding:2px 9px;font-size:12px;font-weight:600;white-space:nowrap}
.ats-nivel.n-critico{background:var(--danger);color:#fff}
.ats-nivel.n-alto{background:rgba(192,57,43,.15);color:var(--danger)}
.ats-nivel.n-moderado{background:rgba(184,134,11,.18);color:var(--warn)}
.ats-nivel.n-bajo{background:rgba(27,122,61,.13);color:var(--ok)}
.ats-nivel.n-sin{background:var(--surface2);color:var(--muted)}

.ats-avisos{list-style:none;margin:0 0 16px;padding:0;display:grid;gap:6px}
.ats-avisos li{font-size:13px;line-height:1.5;padding:8px 12px;border-radius:8px;
  border-left:3px solid var(--border);background:var(--surface2)}
.ats-avisos li.av-critico{border-left-color:var(--danger);background:rgba(192,57,43,.08);color:var(--danger);font-weight:600}
.ats-avisos li.av-alto{border-left-color:var(--danger)}
.ats-avisos li.av-aviso{border-left-color:var(--warn)}
.ats-avisos li.av-info{border-left-color:var(--accent)}

.ats-buscar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px}
.ats-buscar input[type=search]{flex:1;min-width:220px;padding:7px 10px;border:1px solid var(--border);
  border-radius:6px;background:var(--input-bg);color:var(--text);font-family:inherit;font-size:13px}

/* Candidatos del IPER: lista densa y marcable, pensada para elegir diez
   de un tirón sin scrollear una tabla ancha en el teléfono. */
.ats-cand{max-height:340px;overflow-y:auto;border:1px solid var(--border);border-radius:var(--radius)}
.ats-cand-it{display:flex;align-items:center;gap:9px;padding:7px 11px;font-size:12.5px;cursor:pointer;
  border-bottom:1px solid var(--border)}
.ats-cand-it:last-child{border-bottom:0}
.ats-cand-it:hover{background:var(--surface2)}
.ats-cand-it.ya{opacity:.5;cursor:default}
.ats-cand-it .c-num{font-weight:600;color:var(--muted);white-space:nowrap}
.ats-cand-it .c-tarea{font-weight:600;color:var(--heading)}
.ats-cand-it .c-pel{flex:1;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Una línea del ATS. Plegada muestra lo que importa en la charla previa;
   abierta, el análisis entero. */
.ats-linea{border:1px solid var(--border);border-radius:var(--radius);margin-bottom:7px;background:var(--card)}
.ats-linea>summary{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:9px 12px;cursor:pointer;font-size:13px}
.ats-linea>summary::-webkit-details-marker{display:none}
.ats-linea[open]>summary{border-bottom:1px solid var(--border)}
.ats-linea .l-pel{font-weight:600;color:var(--heading)}
.ats-linea .l-riesgo{color:var(--muted)}
.l-tag{display:inline-block;border-radius:9px;padding:1px 8px;font-size:11px;background:var(--surface2);color:var(--muted)}
.l-tag.obra{background:rgba(21,101,160,.13);color:var(--accent)}
.l-tag.ajuste{background:rgba(184,134,11,.15);color:var(--warn)}
.l-tag.ok{background:rgba(27,122,61,.13);color:var(--ok)}
.l-tag.pend{background:rgba(192,57,43,.12);color:var(--danger)}
.l-tag.permiso{background:rgba(192,57,43,.12);color:var(--danger);font-weight:600}

.ats-det{padding:11px 13px;font-size:12.5px;line-height:1.6}
.ats-meta{display:flex;flex-wrap:wrap;gap:6px 16px;margin-bottom:9px;color:var(--muted)}
.ats-ctrl{margin:3px 0;color:var(--text)}
.ats-ctrl b{color:var(--heading)}
.ats-ctrl.ajuste{color:var(--warn)}
.ats-ctrl.legal{color:var(--muted);font-size:12px}
.ats-ctrl.ia{color:var(--ia-txt);background:var(--ia-bg);border-left:3px solid var(--ia-line);
  border-radius:6px;padding:5px 9px;margin:7px 0;font-size:12px}
.l-tag.ia{background:var(--ia-bg);color:var(--ia-txt);border:1px solid var(--ia-line)}

/* El análisis propuesto por IA: la misma familia visual que el panel de
   carga asistida (borde punteado ámbar), para que se lea a la primera que
   eso todavía no es un registro — es una propuesta esperando una persona. */
.ia-ats{border:1px dashed var(--ia-line);border-radius:10px;background:var(--ia-bg);padding:12px 14px;margin-bottom:14px}
.ia-ats .ia-acciones{margin:0}
.ia-ats select{max-width:340px}
.ia-prop{display:flex;gap:10px;align-items:flex-start;background:var(--card);border:1px solid var(--border);
  border-left:3px solid var(--ok);border-radius:8px;padding:10px 12px;margin-bottom:8px;cursor:pointer}
.ia-prop.conf-media{border-left-color:var(--warn)}
.ia-prop.conf-baja{border-left-color:var(--danger)}
.ia-prop>input{width:17px;height:17px;margin-top:3px;flex:0 0 auto}
.ia-prop:has(>input:checked){background:rgba(27,122,61,.06)}
.ia-prop-cuerpo{flex:1 1 auto;min-width:0;font-size:12.5px;line-height:1.55}
.ia-prop-cab{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;margin-bottom:5px}
.ia-prop-cab b{color:var(--heading);font-size:13px}
.ia-prop-meta{display:flex;flex-wrap:wrap;gap:4px 14px;color:var(--muted);font-size:12px;margin-bottom:6px}
.ia-prop-cuerpo small{display:block;margin-top:6px;font-size:11.5px}
.ats-acciones{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:10px}
.ats-editar,.ats-nuevo{margin-top:10px}
.ats-editar>summary,.ats-nuevo>summary{cursor:pointer;font-size:12.5px;font-weight:600;color:var(--accent);padding:5px 0}
.ats-bloqueo{font-size:13px;line-height:1.5;padding:9px 12px;border-radius:8px;
  border-left:3px solid var(--warn);background:rgba(184,134,11,.08);margin:0 0 10px}
