/* ===================== TIPOGRAFÍA (04/09/2026) ============================
   Inter autohospedada. Antes venía de Google Fonts, que ponía DOS dominios externos
   en el camino crítico del render: fonts.googleapis.com para el CSS y
   fonts.gstatic.com para el archivo. Desde el 4G de una obra eso son dos DNS y dos
   handshakes TLS antes de ver texto con la tipografía correcta — y si alguno va
   lento, el portal se ve con la fuente del sistema.

   Es la fuente VARIABLE (eje 400–700 en un solo archivo): antes se pedían SEIS
   grosores sueltos (300 a 800) y solo se usan cuatro. El 300 y el 800 no los usa
   ninguna pantalla.

   `unicode-range` hace que latin-ext solo se baje si aparece un carácter que lo
   necesite. El español entra entero en «latin»: los 48 KB son todo lo que viaja.

   Licencia: public/fonts/LICENCIA-Inter.txt (OFL 1.1). */
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:400 700;
  font-display:swap;
  src:url('/public/fonts/inter-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}
@font-face{
  font-family:'Inter';
  font-style:normal;
  font-weight:400 700;
  font-display:swap;
  src:url('/public/fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ============================================================================
   med-ui.css — Paso 1: tabla operativa + microinteracciones
   Portal operativo de obra · Constructora Mediterráneo

   PALETA CORPORATIVA SIN CAMBIOS. Esto solo arregla jerarquía y ritmo.

   INTERRUPTOR: todo cuelga de .med-v2 en el <body>.
   Para revertir el reskin entero, sacá esa clase del body. Nada más.

   Alcance de este archivo (paso 1):
     · thead pegajoso con scroll interno en la tabla
     · separadores y hover en la paleta de la casa (no slate)
     · zebra donde la fila NO codifica estado por color
     · transiciones y foco visible (hoy: 0 de 54 botones tenían transición)
   Fuera de alcance (paso 2 y 3): KPIs con semáforo, barra de comandos,
   sistema de botones y unificación de tokens.
   ========================================================================= */

/* ---- TOKENS — fuente única ---------------------------------------------
   Antes vivían duplicados en un bloque :root dentro del <style> de cada
   página: seis copias en tres versiones distintas (a cerrados.html y
   admin.html les faltaban verde-700, verde-100 y naranja-300; login.html
   tenía cuatro tokens; bugs.html ninguno, ni siquiera la fuente Inter).
   Cambiar un color de marca obligaba a editar seis archivos.

   Van en :root y no en .med-v2 para que valgan también fuera del reskin.
   Los valores de marca son EXACTAMENTE los que ya estaban en producción. */
:root{
  /* Marca (sin cambios) */
  --med-verde-900:#18352F; --med-verde-800:#20413A; --med-verde-700:#2e4a43;
  --med-verde-500:#3E7C5A; --med-verde-100:#e3e8e6;
  --med-naranja:#F86000;   --med-naranja-300:#f0a571;
  --med-ink:#1f2a27;       --med-ink-soft:#5b6b66;
  --med-fondo:#f4f6f5;     --med-blanco:#ffffff;
  --med-gris-barra:#d0d6d3;
  --med-radio:10px;        --med-radio-sm:6px;
  --med-sombra:0 1px 3px rgba(24,53,47,.10),0 1px 2px rgba(24,53,47,.06);

  /* Derivados calculados desde el verde y el naranja. Ningún color nuevo. */
  --med-naranja-600:#e25700;  /* hover del primario */
  --med-naranja-700:#c44d00;
  --med-verde-050:#f1f5f4;    /* verde-100 aclarado — hover de fila */
  --med-linea:#e6ebe9;        /* borde neutro teñido de verde, reemplaza slate-100 */
  --med-linea-fuerte:#d5ddda;
  --med-zebra:#fafbfa;        /* franja alterna, apenas perceptible */

  /* Estado. Rojo y verde de semáforo: no son colores de marca, son señales. */
  --med-critico:#b91c1c;   --med-critico-bg:#fef2f2;  --med-critico-bd:#fecaca;

  /* Elevación: DOS niveles, no tres escalas sueltas de Tailwind */
  --med-el-1:0 1px 2px rgba(24,53,47,.06), 0 1px 3px rgba(24,53,47,.10);
  --med-el-2:0 4px 12px rgba(24,53,47,.10), 0 2px 4px rgba(24,53,47,.06);
  --med-el-modal:0 24px 48px -12px rgba(24,53,47,.35);

  /* Radios: DOS. Controles a 6px, contenedores a 10px. */
  --r-sm:6px; --r-md:10px;

  --med-t-rapida:120ms cubic-bezier(.4,0,.2,1);
  --med-t-media:180ms cubic-bezier(.4,0,.2,1);
}

/* ===================== 1. TABLA: CABECERA PEGAJOSA ======================= */
/* El contenedor tenía overflow-hidden, que anula position:sticky. Se cambia
   por scroll propio: la tabla scrollea adentro y la cabecera queda fija.
   min-height evita que en pantallas bajas quede una ventanita inútil. */
.med-v2 .tabla-wrap{
  background:#fff;
  border:1px solid var(--med-linea);
  border-radius:10px;
  box-shadow:var(--med-el-1);
  overflow:auto;
  max-height:calc(100vh - 230px);
  min-height:320px;
}
@media (max-width:768px){
  .med-v2 .tabla-wrap{ max-height:none; min-height:0; }  /* en móvil scrollea la página */
}

.med-v2 .tabla-wrap thead th,
.med-v2 thead.med-thead th{
  position:sticky; top:0; z-index:5;
  background:var(--med-verde-700,#2e4a43); color:#fff;
  padding:12px; text-align:left; white-space:nowrap;
  font-size:11px; font-weight:600; letter-spacing:.07em; text-transform:uppercase;
  border-bottom:2px solid var(--med-verde-900,#18352F);
}
.med-v2 thead.med-thead th.sortable{ transition:background-color var(--med-t-rapida); }

/* ===================== 2. TABLA: FILAS =================================== */
/* Separador y hover en la paleta de la casa. Antes: border-slate-100 y un
   hover #f1f5f9 (slate) que no pertenece a la identidad. */
.med-v2 tbody td{
  border-top:none !important;
  border-bottom:1px solid var(--med-linea);
  font-variant-numeric:tabular-nums;   /* días y fechas dejan de bailar */
}
.med-v2 tbody tr:last-child > td{ border-bottom:none; }
.med-v2 tbody tr{ transition:background-color var(--med-t-rapida); }

/* Hover corporativo. Pisa el .row:hover{#f1f5f9 !important} existente. */
.med-v2 tr.row:hover,
.med-v2 tbody tr:hover{ background:var(--med-verde-050) !important; }

/* Los estados de fila mandan sobre el hover neutro: una fila vencida sigue
   leyéndose vencida cuando el mouse pasa por encima. */
.med-v2 tr.row-vencido:hover{ background:#fee2e2 !important; }
.med-v2 tr.row-alta-pendiente:hover{ background:#fef3c7 !important; }
.med-v2 tr.row-completed:hover{ background:#dcfce7 !important; }
.med-v2 tr.linea-hoy:hover > td,
.med-v2 tr.fila-futura:hover > td{ background:inherit; }

/* ===================== 3. TABLA: ZEBRA (selectiva) ====================== */
/* Solo donde la fila NO codifica estado por color. En la tabla de pendientes
   las filas ya se pintan por estado (vencido / alta / completado) y sumar
   zebra encima ensucia la lectura: por eso ahí la zebra queda apagada y se
   activa por página con .zebra en el contenedor. */
.med-v2 .tabla-wrap.zebra tbody tr:nth-child(even):not(.linea-hoy):not(.fila-futura):not(.detail-row):not([class*="row-"]) > td{
  background:var(--med-zebra);
}

/* ===================== 4. MICROINTERACCIONES ============================ */
/* Antes de esto: 0 de 54 botones tenían transición. Todo saltaba. */
.med-v2 button,
.med-v2 select,
.med-v2 input,
.med-v2 textarea,
.med-v2 .tab,
.med-v2 a[class*="px-"]{
  transition:background-color var(--med-t-rapida),
             border-color var(--med-t-rapida),
             color var(--med-t-rapida),
             box-shadow var(--med-t-rapida),
             opacity var(--med-t-rapida);
}
.med-v2 button:active:not([disabled]){ transform:translateY(.5px); }

/* Foco visible en naranja corporativo — reemplaza el ring azul de Tailwind.
   :focus-visible = solo teclado, no molesta al mouse. */
.med-v2 button:focus-visible,
.med-v2 [role="button"]:focus-visible,
.med-v2 a:focus-visible{
  outline:none; box-shadow:0 0 0 3px rgba(248,96,0,.28);
}
.med-v2 input:focus-visible,
.med-v2 select:focus-visible,
.med-v2 textarea:focus-visible{
  outline:none;
  border-color:var(--med-verde-500,#3E7C5A);
  box-shadow:0 0 0 3px rgba(62,124,90,.16);
}

/* Botones secundarios blancos: hover en verde de la casa, no en slate */
.med-v2 button.bg-white:hover:not([disabled]){
  background:var(--med-verde-050) !important;
  border-color:var(--med-verde-500,#3E7C5A) !important;
}

/* Tabs: subrayado que crece en vez de un cambio de color seco */
.med-v2 .tab{ position:relative; }
.med-v2 .tab::after{
  content:''; position:absolute; left:8px; right:8px; bottom:0; height:2px;
  background:var(--med-naranja,#F86000); border-radius:2px;
  transform:scaleX(0); transform-origin:left;
  transition:transform var(--med-t-media);
}
.med-v2 .tab.active::after{ transform:scaleX(1); }

/* Fila recién guardada: pulso naranja en su lugar, sin tapar la tabla */
@keyframes med-pulso{ 0%{ background:#fff5ef; } 100%{ background:transparent; } }
.med-v2 tr.recien-guardado > td{ animation:med-pulso 1.2s ease-out; }

/* Skeleton en el verde de la casa, no en gris genérico */
.med-v2 .skel{
  background:linear-gradient(90deg,var(--med-verde-050) 25%,#fff 50%,var(--med-verde-050) 75%);
  background-size:200% 100%;
  animation:med-brillo 1.4s infinite;
}
@keyframes med-brillo{ 100%{ background-position:-200% 0; } }

/* Cards con sombra: elevación al pasar por encima */
.med-v2 .stat-card{ transition:box-shadow var(--med-t-media), transform var(--med-t-media); }
.med-v2 .stat-card:hover{ transform:translateY(-1px); box-shadow:var(--med-el-2); }

/* Quien pidió menos movimiento en su sistema, no lo recibe */
@media (prefers-reduced-motion:reduce){
  .med-v2 *,.med-v2 *::before,.med-v2 *::after{
    animation-duration:.01ms !important;
    transition-duration:.01ms !important;
  }
}

/* ===================== 5. IMPRESIÓN ===================================== */
/* La cabecera pegajosa y el scroll interno rompen el PDF del informe. */
@media print{
  .med-v2 .tabla-wrap{
    max-height:none; min-height:0; overflow:visible;
    border:none; box-shadow:none;
  }
  .med-v2 .tabla-wrap thead th,
  .med-v2 thead.med-thead th{
    position:static;
    background:#fff !important; color:#000 !important;
    border-bottom:2px solid #000;
  }
  .med-v2 .tabla-wrap.zebra tbody tr:nth-child(even) > td{ background:#fff; }
}

/* ============================================================================
   PASO 2 — Jerarquía: KPIs con semáforo y barra de comandos ordenada
   Sigue todo bajo .med-v2. Misma paleta.
   ========================================================================= */

/* ===================== 6. KPIs QUE HABLAN =============================== */
/* Antes: los 5 KPI salían del mismo tamaño y el mismo verde, porque el
   reskin pisó con `.stat-num{color:var(--med-verde-900)}` los colores que el
   render ya mandaba. Resultado: "4 vencidos" pesaba igual que "12 abiertos".
   Ahora el color entra SOLO cuando hay un problema, y en cero se apaga. */
.med-v2 #stats{ gap:12px; }
.med-v2 .stat-card{
  border-left:3px solid var(--med-verde-100);
  padding:12px 16px;
  border-radius:10px;
  box-shadow:var(--med-el-1);
  transition:box-shadow var(--med-t-media), transform var(--med-t-media),
             border-color var(--med-t-media);
}
.med-v2 .stat-card .stat-num{
  font-size:28px; font-weight:700; line-height:1.05; letter-spacing:-.02em;
}
.med-v2 .stat-card .stat-label{
  font-size:11px; font-weight:600; letter-spacing:.07em; text-transform:uppercase;
  color:var(--med-ink-soft); margin-top:2px; line-height:1.3;
}
/* El dato que manda en la pantalla: más grande que el resto */
.med-v2 .stat-card--hero .stat-num{ font-size:34px; }

/* Semáforo. Especificidad 0-2-0 para ganarle al .stat-num del reskin viejo. */
.med-v2 .stat-card--critico{ border-left-color:#b91c1c; }
.med-v2 .stat-card--critico .stat-num{ color:#b91c1c; }
.med-v2 .stat-card--riesgo{ border-left-color:var(--med-naranja,#F86000); }
.med-v2 .stat-card--riesgo .stat-num{ color:var(--med-naranja,#F86000); }
.med-v2 .stat-card--neutro .stat-num{ color:var(--med-verde-900,#18352F); }

/* Cero problemas = sin grito. Un rojo permanente deja de mirarse. */
.med-v2 .stat-card.is-cero{ border-left-color:var(--med-verde-100); }
.med-v2 .stat-card.is-cero .stat-num{ color:var(--med-ink-soft,#5b6b66); }

/* BUG-007: los KPI son botones y filtran el listado.
   El KPI activo se marca con el verde de la casa —no con otro color— porque no es un
   estado nuevo del dato: es "estás mirando esto". El número conserva su semáforo. */
.med-v2 .stat-card{ font:inherit; color:inherit; text-align:left; width:100%; cursor:pointer; }
.med-v2 .stat-card.is-activo{
  border-color:var(--med-verde-600,#2f6f5e);
  box-shadow:0 0 0 2px color-mix(in srgb, var(--med-verde-600,#2f6f5e) 22%, transparent), var(--med-el-1);
}
.med-v2 .stat-card.is-activo .stat-label{ color:var(--med-verde-900,#18352F); }
/* En cero no se puede tocar: un filtro vacío deja la tabla en blanco sin explicar por qué. */
.med-v2 .stat-card:disabled{ cursor:default; }
.med-v2 .stat-card:disabled:hover{ transform:none; box-shadow:var(--med-el-1); }

/* ===================== 7. BOTONES: TRES NIVELES ========================= */
/* Se adelantan acá porque la barra los necesita para tener jerarquía.
   La migración del resto de la app (30+ variantes sueltas) es el paso 3. */
/* `:not(.hidden)` es obligatorio, igual que en .menu-item: varios botones se
   ocultan por rol o por contexto con la clase .hidden de Tailwind (btnUndo,
   navAdmin, el "+ Nueva acta" de actas, que es solo para Dirección). Sin el
   :not, esta regla (0-2-0) le gana a .hidden (0-1-0) y los muestra a todos. */
.med-v2 .btn:not(.hidden){
  display:inline-flex; align-items:center; justify-content:center; gap:6px;
  height:32px; padding:0 12px;
  font-size:13px; font-weight:600; line-height:1; white-space:nowrap;
  border:1px solid transparent; border-radius:6px; cursor:pointer;
  text-decoration:none;
}
.med-v2 .btn-primario{
  background:var(--med-naranja,#F86000); color:#fff; box-shadow:var(--med-el-1);
}
.med-v2 .btn-primario:hover{ background:#e25700; box-shadow:var(--med-el-2); }
.med-v2 .btn-secundario{
  background:#fff; color:var(--med-verde-800,#20413A); border-color:var(--med-linea-fuerte);
}
.med-v2 .btn-secundario:hover{
  background:var(--med-verde-050); border-color:var(--med-verde-500,#3E7C5A);
  color:var(--med-verde-900,#18352F);
}
/* Navegación y acciones raras: presentes, sin pelear por atención */
.med-v2 .btn-fantasma{ background:transparent; color:var(--med-ink-soft,#5b6b66); }
.med-v2 .btn-fantasma:hover{ background:var(--med-verde-050); color:var(--med-verde-900,#18352F); }
.med-v2 .btn-icono{ width:32px; padding:0; font-size:16px; }

/* ===================== 8. BARRA DE COMANDOS ============================= */
/* Antes: 13 controles en fila, todos con el mismo peso. Ahora navegación
   (fantasma) · acciones (secundario) · una sola acción primaria · el resto
   detrás de "⋯". */
.med-v2 .barra-acciones{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.med-v2 .barra-acciones .sep{
  width:1px; height:20px; background:var(--med-linea); margin:0 2px;
}

.med-v2 .menu-mas{ position:relative; }
.med-v2 .menu-panel{
  position:absolute; right:0; top:calc(100% + 6px); z-index:50;
  min-width:212px; padding:6px;
  background:#fff; border:1px solid var(--med-linea);
  border-radius:10px; box-shadow:var(--med-el-2);
}
.med-v2 .menu-panel[hidden]{ display:none; }

/* `:not(.hidden)` es deliberado: navAdmin se oculta a los no-admin con la
   clase .hidden de Tailwind. Sin este :not, esta regla (0-3-0) le ganaría a
   .hidden (0-1-0) y el acceso a Administración quedaría visible para todos. */
.med-v2 .menu-panel .menu-item:not(.hidden){
  display:flex; align-items:center; gap:8px; width:100%;
  padding:7px 10px; border:none; background:none; border-radius:6px;
  font-size:13px; font-weight:500; color:var(--med-ink,#1f2a27);
  text-align:left; text-decoration:none; cursor:pointer;
}
.med-v2 .menu-panel .menu-item:hover{ background:var(--med-verde-050); }
.med-v2 .menu-panel .menu-sep{
  height:1px; margin:5px 6px; background:var(--med-linea);
}
.med-v2 .menu-panel .menu-item--salir{ color:var(--med-ink-soft,#5b6b66); }

@media (max-width:768px){
  .med-v2 .menu-panel{ right:auto; left:0; min-width:190px; }
}

/* ===================== 9. RECUPERAR ALTO DE PANTALLA ==================== */
/* Medido en 1440x900: antes del primer dato había 562px de cromo sobre 900
   de viewport. La barra ordenada bajó a 518; estas reglas la dejan en ~430,
   sin sacar ningún control de la pantalla. */

/* Banda: el logo no necesita 72px de alto para leerse */
.med-v2 .med-band-inner{ padding:10px 24px; }
.med-v2 .med-band img{ height:48px; }

/* Ritmo entre bloques: 20px era generoso de más entre header, KPIs y filtros */
.med-v2 header.mb-5{ margin-bottom:12px; }
.med-v2 #stats.mb-5{ margin-bottom:12px; }

/* Título: el overline ya dice la obra, el h1 no necesita 24px */
.med-v2 header h1{ font-size:20px; line-height:1.25; letter-spacing:-.015em; }

/* Filtros: controles a 30px de alto para que entren en una fila.
   Son secundarios frente a la tabla; no deben pesar como la barra. */
.med-v2 .filtros{ margin-top:8px; margin-bottom:10px; gap:6px; }
.med-v2 .filtros > label,
.med-v2 .filtros > select,
.med-v2 .filtros > input{
  height:30px; padding:0 10px; font-size:12.5px;
  border-radius:6px; border-color:var(--med-linea-fuerte);
}
.med-v2 .filtros > label{ display:inline-flex; align-items:center; gap:6px; }
.med-v2 .filtros > label:hover{ background:var(--med-verde-050); }

/* ============================================================================
   PASO 3 — Un solo sistema de controles
   Antes: 30+ variantes de botón sueltas, tres convenciones conviviendo
   (utilidades Tailwind, el .btn/.btn-primary propio de admin.html, y colores
   inline), 6 radios distintos y 3 escalas de sombra.
   ========================================================================= */

/* ===================== 10. BOTONES: TAMAÑOS ============================= */
/* .btn base (32px) está en la sección 7. Acá los tamaños que faltaban. */
.med-v2 .btn-lg{ height:38px; padding:0 16px; font-size:13.5px; border-radius:var(--r-sm); }
.med-v2 .btn-sm{ height:26px; padding:0 9px; font-size:12px; }
.med-v2 .btn-xs{ height:22px; padding:0 7px; font-size:11px; font-weight:500; }

/* Peligro: borrar, rechazar, descartar */
.med-v2 .btn-peligro{
  background:#fff; color:var(--med-critico); border-color:var(--med-critico-bd);
}
.med-v2 .btn-peligro:hover{ background:var(--med-critico-bg); }

/* Variantes de acento que ya existían inline en el JS, ahora nombradas */
.med-v2 .btn-verde{ background:var(--med-verde-900); color:#fff; }
.med-v2 .btn-verde:hover{ background:var(--med-verde-800); }

/* En un flex de modal, el par Cancelar/Guardar reparte a la mitad */
.med-v2 .btn.flex-1{ flex:1 1 0%; }
.med-v2 .btn.w-full{ width:100%; }

/* ===================== 11. CAMPOS ======================================= */
/* Reemplaza las 20 repeticiones de
   "w-full px-3 py-2 border border-slate-300 rounded-lg text-sm" y sus
   variantes con focus:ring-blue-500. */
.med-v2 .campo{
  display:block; width:100%; height:36px;
  padding:0 12px; font-size:13px; font-family:inherit; color:var(--med-ink);
  background:#fff; border:1px solid var(--med-linea-fuerte);
  border-radius:var(--r-sm);
  transition:border-color var(--med-t-rapida), box-shadow var(--med-t-rapida);
}
.med-v2 textarea.campo{ height:auto; min-height:76px; padding:9px 12px; line-height:1.5; resize:vertical; }
.med-v2 select.campo{ padding-right:28px; }
.med-v2 .campo:hover{ border-color:var(--med-gris-barra); }
/* :focus, no :focus-visible: en un campo de texto el foco debe verse siempre,
   se haya llegado con el mouse o con Tab. */
.med-v2 .campo:focus{
  outline:none; border-color:var(--med-verde-500);
  box-shadow:0 0 0 3px rgba(62,124,90,.16);
}
.med-v2 .campo::placeholder{ color:#9aa8a3; }
.med-v2 .campo-label{
  display:block; margin-bottom:4px;
  font-size:11px; font-weight:600; letter-spacing:.06em; text-transform:uppercase;
  color:var(--med-ink-soft);
}

/* ===================== 12. NORMALIZACIÓN DE FORMA ======================= */
/* De 6 radios a 2 y de 3 sombras a 2, sin tocar el markup: se reasignan las
   utilidades de Tailwind que ya están escritas en las páginas. */
.med-v2 .rounded{ border-radius:var(--r-sm); }
.med-v2 .rounded-lg{ border-radius:var(--r-sm); }
.med-v2 .rounded-2xl{ border-radius:var(--r-md); }
.med-v2 .shadow{ box-shadow:var(--med-el-1); }
.med-v2 .shadow-sm{ box-shadow:var(--med-el-1); }
.med-v2 .shadow-2xl{ box-shadow:var(--med-el-modal); }
/* .rounded-full se deja: pills y avatares lo necesitan redondo de verdad. */

/* ===================== 13. MODALES ====================================== */
.med-v2 .modal-acciones{ display:flex; gap:8px; }
.med-v2 .modal-acciones .btn{ flex:1 1 0%; }

/* ===================== 14. ADMIN: UN SOLO SISTEMA ======================= */
/* admin.html traía su propio .btn/.btn-primary/.btn-light/.btn-danger, con
   otro alto y otro radio. Se migró a las clases de acá; estos alias quedan
   por si algún fragmento generado en JS todavía los usa. */
.med-v2 .btn-primary{ background:var(--med-naranja); color:#fff; border-color:transparent; }
.med-v2 .btn-primary:hover{ background:var(--med-naranja-600); }
.med-v2 .btn-light{ background:#fff; color:var(--med-verde-800); border-color:var(--med-linea-fuerte); }
.med-v2 .btn-light:hover{ background:var(--med-verde-050); border-color:var(--med-verde-500); }
.med-v2 .btn-danger{ background:#fff; color:var(--med-critico); border-color:var(--med-critico-bd); }
.med-v2 .btn-danger:hover{ background:var(--med-critico-bg); }
.med-v2 .campo-sm{ height:30px; padding:0 10px; font-size:12.5px; }

/* Alias: admin.html usa .inp en 23 lugares, varios generados en JS.
   Se le da el mismo cuerpo que .campo en vez de renombrarlos uno por uno. */
.med-v2 .inp{
  display:block; width:100%; height:36px; padding:0 12px;
  font-size:13px; font-family:inherit; color:var(--med-ink);
  background:#fff; border:1px solid var(--med-linea-fuerte); border-radius:var(--r-sm);
  transition:border-color var(--med-t-rapida), box-shadow var(--med-t-rapida);
}
.med-v2 textarea.inp{ height:auto; min-height:76px; padding:9px 12px; line-height:1.5; }
.med-v2 .inp:focus{
  outline:none; border-color:var(--med-verde-500);
  box-shadow:0 0 0 3px rgba(62,124,90,.16);
}

/* ===================== 15. ÚLTIMOS RESTOS DE FORMA ===================== */
/* Los campos editables dentro de la fila (.cell) y las pestañas traían su
   propio radio en el <style> de la página: 4px y 8px. Con esto quedan dos
   radios en toda la app — 6px controles, 10px contenedores — más el
   redondo completo de pills y avatares. */
.med-v2 input.cell, .med-v2 select.cell{ border-radius:var(--r-sm); }
.med-v2 input.cell:hover, .med-v2 select.cell:hover{ border-color:var(--med-gris-barra); }
.med-v2 .tab{ border-radius:var(--r-sm) var(--r-sm) 0 0; }
.med-v2 .tab:hover{ background:var(--med-verde-050); }
.med-v2 .tab.active{ border-color:var(--med-linea); }

/* ===================== 16. CHIP DE USUARIO ============================== */
/* BUG-002 (Nibol): "mejor simetría en los botones del panel". El paso 3
   unificó los botones, pero el chip de usuario quedó fuera del sistema con
   sus clases originales: 38px de alto contra 32 del resto, y en las otras
   páginas ~26px. Centrado sí estaba; lo que rompía la simetría era el alto.
   Sigue redondo a propósito — es un chip de identidad, no un botón. */
.med-v2 #userBadge{
  display:inline-flex; align-items:center; gap:8px;
  height:32px; padding:0 10px 0 4px;
  font-size:13px; font-weight:500; color:var(--med-ink);
  background:#fff; border:1px solid var(--med-linea-fuerte);
  border-radius:9999px; cursor:pointer; white-space:nowrap;
  transition:background-color var(--med-t-rapida), border-color var(--med-t-rapida);
}
.med-v2 #userBadge:hover{ background:var(--med-verde-050); border-color:var(--med-verde-500); }
.med-v2 #userBadge:focus-visible{ outline:none; box-shadow:0 0 0 3px rgba(248,96,0,.28); }
/* El avatar entra en los 32px del chip sin estirarlo. El fallback (la inicial,
   cuando no hay foto cargada) va igual: las clases w-7 h-7 lo dejaban en 28px
   y apretaba contra el borde del chip. */
.med-v2 #userBadge img,
.med-v2 #userBadge .avatar-fallback{
  width:24px; height:24px; border-radius:9999px; object-fit:cover; flex:none;
  font-size:11px; line-height:24px;
}
/* En impedimentos y actas es un <span> sin avatar: mismo alto, padding parejo */
.med-v2 span#userBadge{ padding:0 12px; cursor:default; }
.med-v2 span#userBadge:hover{ background:#fff; border-color:var(--med-linea-fuerte); }

/* ---- Chips de impacto ---------------------------------------------------
   Los cuatro impactos de un pendiente (Retrasa · Bloquea · Sobrecosto ·
   Seguridad). Reemplazan al segundo textarea del formulario de alta: era el
   campo que más se escribía y el que menos se leía.

   Sin colores nuevos: el seleccionado usa el naranja de marca, como el resto
   de lo que está activo en el portal. Los cuatro se ven iguales entre sí a
   propósito — no son un semáforo, son una clasificación; el peso de
   "Seguridad" lo pone el dato, no el color del botón. */
.chip-impacto{
  display:inline-flex; align-items:center; gap:6px;
  height:32px; padding:0 12px;
  font-size:13px; font-weight:500; line-height:1;
  color:var(--med-ink); background:#fff;
  border:1px solid var(--med-linea-fuerte); border-radius:9999px;
  cursor:pointer; white-space:nowrap; user-select:none;
  transition:background-color var(--med-t-rapida,.15s), border-color var(--med-t-rapida,.15s), color var(--med-t-rapida,.15s);
}
.chip-impacto:hover{ background:var(--med-verde-050); border-color:var(--med-verde-500); }
.chip-impacto:focus-visible{ outline:none; box-shadow:0 0 0 3px rgba(248,96,0,.28); }
.chip-impacto[aria-pressed="true"]{
  background:var(--med-naranja); border-color:var(--med-naranja); color:#fff; font-weight:600;
}
.chip-impacto[aria-pressed="true"]:hover{ background:var(--med-naranja-600); border-color:var(--med-naranja-600); }
/* Marca cuando falta elegir: mismo tratamiento que un campo requerido vacío */
.chips-faltan .chip-impacto{ border-color:#dc2626; }

/* La etiqueta que muestra el impacto ya elegido, en la fila y en el detalle.
   Es lectura, no control: más chica, sin borde redondo completo. */
.tag-impacto{
  display:inline-flex; align-items:center;
  padding:1px 7px; border-radius:var(--med-radio-sm,6px);
  font-size:11px; font-weight:500; line-height:1.5;
  color:var(--med-verde-900); background:var(--med-verde-100);
  border:1px solid var(--med-linea-fuerte);
}

/* ---- Ventanas (modales) -------------------------------------------------
   Vivían dentro del <style> de actas.html. Al necesitarlas también en el
   tablero había que copiarlas, que es cómo empiezan las divergencias. Acá
   valen para todas las páginas, con o sin el reskin.

   Recordatorio de por qué existen: estas clases NO estaban definidas cuando
   se escribieron los primeros modales por JS. El navegador ignora una clase
   inexistente sin decir nada, así que se dibujaban en el flujo de la página,
   al final, y cada apertura apilaba una copia más (trampa #31). */
.modal-backdrop{
  position:fixed; inset:0; z-index:60; background:rgba(15,23,42,.45);
  display:flex; align-items:center; justify-content:center; padding:16px;
}
.modal-box{
  display:flex; flex-direction:column; width:100%; max-width:640px; max-height:90vh;
  background:#fff; border-radius:16px;
  box-shadow:0 25px 50px -12px rgba(15,23,42,.35); overflow:hidden;
}
.modal-head{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:16px 20px; border-bottom:1px solid var(--med-linea,#e2e8f0);
}
.modal-body{ flex:1; overflow-y:auto; padding:16px 20px; }
.modal-foot{
  display:flex; gap:8px; justify-content:flex-end;
  padding:14px 20px; border-top:1px solid var(--med-linea,#e2e8f0); background:#f8fafc;
}
@media print{ .modal-backdrop{ display:none !important; } }

/* ---- Botón de deshacer dentro de un aviso -------------------------------
   La salida va donde ocurrió la acción, no en un menú. Es lo que permite
   sacar los confirm() de las acciones que sí se pueden revertir: preguntar
   antes cuesta un clic SIEMPRE; ofrecer la vuelta atrás cuesta un clic solo
   cuando alguien se equivocó. */
.toast-accion{
  margin-left:10px; padding:2px 10px;
  font-size:12px; font-weight:600; line-height:1.6;
  color:inherit; background:rgba(255,255,255,.18);
  border:1px solid currentColor; border-radius:9999px;
  cursor:pointer; white-space:nowrap; opacity:.95;
}
.toast-accion:hover{ background:rgba(255,255,255,.32); opacity:1; }
.toast-accion:focus-visible{ outline:none; box-shadow:0 0 0 3px rgba(248,96,0,.35); }

/* ============================================================================
   TARJETAS EN CELULAR — abajo de 768 px
   Decisión de Julio: primero pulir el escritorio, la móvil al final.

   La tabla tiene 10 columnas. En un teléfono de 375 px eso eran 1.046 px de
   tabla en 341 de pantalla: 705 px de scroll horizontal, con una mano ocupada
   en obra. Acá cada fila pasa a ser una tarjeta.

   NO hay un segundo render: es la MISMA fila, reordenada por CSS. Un `rowCard()`
   aparte habría sido una copia del render, y las copias se separan — es lo que
   produjo el BUG-006 y lo que se estuvo sacando toda la sesión. Las celdas
   traen su rol (.celda-check, .celda-texto, .celda-dato con data-label) y el
   CSS decide qué mostrar y dónde.
   ========================================================================= */
@media (max-width:768px){
  /* La cabecera de columnas no significa nada cuando no hay columnas */
  .med-v2 .tabla-tarjetas thead{ display:none; }

  .med-v2 .tabla-tarjetas,
  .med-v2 .tabla-tarjetas table,
  .med-v2 .tabla-tarjetas tbody,
  .med-v2 .tabla-tarjetas tr,
  .med-v2 .tabla-tarjetas td{ display:block; width:auto; }

  /* El contenedor deja de ser una caja con scroll propio: scrollea la página */
  .med-v2 .tabla-tarjetas{
    border:none; box-shadow:none; background:transparent;
    overflow:visible; max-height:none; min-height:0; padding:0;
  }

  /* La tarjeta es una grilla de dos columnas: así las etiquetas y sus valores
     quedan alineados en filas parejas. Apilando inline-blocks se desalineaban
     en cuanto un dato era más alto que el de al lado. */
  .med-v2 .tabla-tarjetas #tbody tr[data-id]{
    display:grid !important;
    grid-template-columns:1fr 1fr;
    gap:8px 12px;
    align-items:start;
    position:relative;
    margin:0 0 10px;
    padding:10px 12px 12px 40px;
    background:#fff;
    border:1px solid var(--med-linea);
    border-left-width:4px;
    border-radius:10px;
    box-shadow:var(--med-el-1, 0 1px 3px rgba(24,53,47,.10));
  }
  /* El estado, que en la tabla era el color de la fila, acá es el borde
     izquierdo: en una tarjeta el fondo de color entero cansa la vista. */
  .med-v2 .tabla-tarjetas #tbody tr[data-id]{ border-left-color:var(--med-linea-fuerte); }
  .med-v2 .tabla-tarjetas #tbody tr.row-vencido{ border-left-color:#dc2626; }
  .med-v2 .tabla-tarjetas #tbody tr.row-alta-pendiente{ border-left-color:var(--med-naranja); }
  .med-v2 .tabla-tarjetas #tbody tr.row-completed{ border-left-color:#16a34a; }
  .med-v2 .tabla-tarjetas #tbody tr[data-id]{ background:#fff !important; }
  .med-v2 .tabla-tarjetas tbody tr:hover{ background:#fff !important; }

  .med-v2 .tabla-tarjetas #tbody td{ padding:0 !important; border:none; }

  .med-v2 .tabla-tarjetas .celda-check{
    position:absolute; top:10px; left:10px; width:26px; text-align:left;
  }
  /* Los carteles de "requiere validación" no entran en 26 px: van abajo de todo */
  .med-v2 .tabla-tarjetas .celda-check > div{
    position:absolute; left:-2px; top:26px; width:150px;
    font-size:9px; line-height:1.2;
  }

  /* El texto ocupa el ancho entero: es lo que se lee primero */
  .med-v2 .tabla-tarjetas .celda-texto{ grid-column:1 / -1; }
  .med-v2 .tabla-tarjetas .celda-texto .item-text{ font-size:14px; line-height:1.35; }

  /* Cada dato con su etiqueta arriba: sin cabecera de tabla, un dato suelto no
     se sabe qué es. */
  .med-v2 .tabla-tarjetas .celda-dato{ text-align:left !important; min-width:0; }
  /* La fecha comprometida va sola y ancha: es el campo que más se toca en obra y
     el que peor se acierta con el pulgar. Además deja a los dos relojes —atraso y
     esperando def.— emparejados en la fila siguiente, sin uno huérfano al final. */
  .med-v2 .tabla-tarjetas .celda-dato[data-label="Comprometida"]{ grid-column:1 / -1; }
  .med-v2 .tabla-tarjetas .celda-dato::before{
    content:attr(data-label);
    display:block;
    font-size:9px; font-weight:600; letter-spacing:.04em; text-transform:uppercase;
    color:var(--med-ink-soft); margin-bottom:2px;
  }
  .med-v2 .tabla-tarjetas .celda-dato .cell{ width:100%; }
  /* Los campos se tocan con el pulgar: 36 px es el mínimo cómodo */
  .med-v2 .tabla-tarjetas .celda-dato select.cell,
  .med-v2 .tabla-tarjetas .celda-dato input.cell{ min-height:36px; font-size:13px; }

  /* Lo que no gana su lugar en un teléfono. Sigue en el escritorio y en el
     detalle: solicitada es histórico, "modificado" es auditoría, y borrar no
     es una acción de campo (además es solo del admin). */
  .med-v2 .tabla-tarjetas .celda-solo-escritorio,
  .med-v2 .tabla-tarjetas .celda-borrar{ display:none !important; }

  /* El detalle ocupa el ancho completo, sin la sangría de la tarjeta */
  .med-v2 .tabla-tarjetas #tbody tr.detail-row{
    display:block !important;
    margin:-6px 0 10px; padding:0; border:none; box-shadow:none; background:transparent;
  }
  .med-v2 .tabla-tarjetas #tbody tr.detail-row td{ padding:0 !important; }

  /* La línea de HOY de impedimentos y las filas especiales no son tarjetas */
  .med-v2 .tabla-tarjetas #tbody tr.linea-hoy{ padding:6px 12px; border-left-width:1px; }
}

/* ---- Tabla → tarjetas, versión simple (Resueltos) -----------------------
   La tabla de pendientes usa `.tabla-tarjetas`, que engancha en `#tbody
   tr[data-id]`. Resueltos no puede usar esa: cuando se agrupa por categoría o por
   responsable dibuja VARIAS tablas en la misma página, y un `id="tbody"` repetido
   sería HTML inválido. Así que engancha por elemento, no por id.

   Medido antes: 522 px de tabla en una pantalla de 375. */
@media (max-width:768px){
  .med-v2 .tabla-tarjetas-simple{
    border:none; box-shadow:none; background:transparent;
    overflow:visible; padding:0;
  }
  .med-v2 .tabla-tarjetas-simple thead{ display:none; }
  .med-v2 .tabla-tarjetas-simple,
  .med-v2 .tabla-tarjetas-simple table,
  .med-v2 .tabla-tarjetas-simple tbody,
  .med-v2 .tabla-tarjetas-simple tr,
  .med-v2 .tabla-tarjetas-simple td{ display:block; width:auto; }

  .med-v2 .tabla-tarjetas-simple tbody tr{
    display:grid !important;
    grid-template-columns:1fr 1fr;
    gap:8px 12px;
    align-items:start;
    margin:0 0 10px;
    padding:10px 12px 12px;
    background:#fff !important;
    border:1px solid var(--med-linea);
    border-left-width:4px;
    border-left-color:var(--med-linea-fuerte);
    border-radius:10px;
    box-shadow:var(--med-el-1, 0 1px 3px rgba(24,53,47,.10));
  }
  /* La fila roja de «tardó más de 30 días» era un fondo entero; en una tarjeta el
     fondo de color cansa la vista, así que pasa al borde, igual que en pendientes. */
  .med-v2 .tabla-tarjetas-simple tbody tr.bg-red-50{ border-left-color:#dc2626; }

  .med-v2 .tabla-tarjetas-simple td{ padding:0 !important; border:none; }
  /* El texto del pendiente ocupa el ancho entero: es lo que se lee primero. */
  .med-v2 .tabla-tarjetas-simple .celda-texto{ grid-column:1 / -1; }
  .med-v2 .tabla-tarjetas-simple .celda-dato{ text-align:left !important; min-width:0; }
  .med-v2 .tabla-tarjetas-simple .celda-dato::before{
    content:attr(data-label);
    display:block;
    font-size:9px; font-weight:600; letter-spacing:.04em; text-transform:uppercase;
    color:var(--med-ink-soft); margin-bottom:2px;
  }
  /* `whitespace-nowrap` es de la vista de tabla: en una tarjeta angosta obliga a
     scrollear para leer una fecha. */
  .med-v2 .tabla-tarjetas-simple td.whitespace-nowrap{ white-space:normal !important; }
}

/* ---- El cromo antes del primer pendiente, en celular ---------------------
   Medido en un teléfono de 375×667: 1.045 px de encabezado, KPIs, pestañas y
   filtros antes de ver el primer pendiente. Una pantalla y media de scroll
   para llegar al dato, con una mano ocupada. La tabla ya no scrollea al
   costado; esto es lo que quedaba. */
@media (max-width:768px){
  /* Los cinco KPI en dos columnas ocupaban ~500 px. Van en una tira horizontal
     que se desliza con el pulgar: se ven dos y medio, y los demás están a un
     empujón. El número sigue siendo lo grande. */
  .med-v2 #stats{
    display:flex !important;
    /* `flex-wrap:nowrap` es obligatorio, no decorativo: Resueltos trae la clase
       `flex-wrap` de Tailwind en el mismo elemento y, si acá no se declara lo
       contrario, los KPI se envuelven en tres filas en vez de deslizarse. Medido:
       media pantalla de alto antes del primer dato. Misma trampa que con #pills. */
    flex-wrap:nowrap !important;
    gap:8px;
    overflow-x:auto;
    scroll-snap-type:x proximity;
    -webkit-overflow-scrolling:touch;
    padding-bottom:4px;
  }
  .med-v2 #stats > *{
    flex:0 0 auto; width:132px; scroll-snap-align:start;
    padding:10px 12px !important;
  }
  .med-v2 #stats .stat-num{ font-size:22px; }
  .med-v2 #stats .stat-label{ font-size:9px; letter-spacing:.03em; }

  /* El logo de la banda ya se achica en móvil; el encabezado de la página se
     aprieta también: el título en dos líneas comía 90 px. */
  .med-v2 h1{ font-size:1.05rem !important; line-height:1.25; }

  /* Las píldoras de responsable son informativas: se pueden deslizar en vez de
     envolverse en tres filas. */
  .med-v2 #pills{
    display:flex !important; flex-wrap:nowrap !important;
    overflow-x:auto; gap:6px; padding-bottom:2px;
  }
  .med-v2 #pills > *{ flex:0 0 auto; }
}

  /* Los filtros, plegados detrás de un botón. Apilados eran ~350 px de controles
     antes del primer pendiente. El buscador y el contador quedan siempre a la
     vista: es lo que se usa parado en obra. */
@media (max-width:768px){
  /* Plegado: se esconden los filtros, NO el buscador ni el contador. Es el mismo
     DOM del escritorio; solo cambia qué se muestra. */
  .med-v2 #filtrosCuerpo > *:not(.siempre-visible){ display:none; }
  .med-v2 #filtrosCuerpo.abierto > *{ display:flex; width:100%; }
  .med-v2 #filtrosCuerpo.abierto > select{ display:block; }
  .med-v2 #filtrosCuerpo{ margin-top:8px; }
  .med-v2 #filtrosCuerpo > .siempre-visible{ width:auto; }
  .med-v2 #filtrosCuerpo > #searchInput{ flex:1 1 auto; min-width:0; }
}
/* El botón de filtros no existe en escritorio: ahí la barra se muestra siempre.
   Va con .med-v2 adelante a propósito: `.med-v2 .btn` declara display:inline-flex
   con especificidad 0-2-0 y le gana a un `.solo-celular` suelto (0-1-0). Es la
   misma trampa que ya había escondido/mostrado botones de rol en el reskin. */
.med-v2 .solo-celular,
.solo-celular{ display:none !important; }
@media (max-width:768px){
  .med-v2 #btnFiltros.solo-celular{ display:flex !important; }
}

/* En escritorio no cambia NADA: el buscador y el contador siguen adentro de la
   misma barra que los filtros, en una línea. Sacarlos a un bloque propio para el
   celular costaba 55 px de cromo en escritorio, que es lo que se acaba de bajar
   en el reskin — no se paga eso por la vista chica. */

/* ===================== PRESENCIA Y ACTIVIDAD (01/09/2026) =================
   Pedido de Julio: ver quién está adentro «como en Google Sheets y Miro», y saber si
   hay gente trabajando antes de desplegar. */

/* El chip es de identidad, no un botón: redondo y del tamaño del resto de la barra
   (32 px), la misma decisión que se tomó para el chip de usuario en el PR #56. */
.chip-presencia{
  display:inline-flex; align-items:center; justify-content:center;
  width:28px; height:28px; border-radius:9999px;
  font-size:11px; font-weight:700; letter-spacing:.02em;
  background:var(--med-verde-100,#DCE9E4); color:var(--med-verde-900,#18352F);
  border:2px solid #fff; box-shadow:var(--med-el-1);
  /* Se superponen como en Sheets: ocupan poco y se lee que son un grupo. */
  margin-left:-6px;
  user-select:none;
}
.chip-presencia:first-child{ margin-left:0; }

/* Panel de últimos cambios */
.act-titulo{
  font-size:11px; font-weight:700; letter-spacing:.07em; text-transform:uppercase;
  color:var(--med-ink-soft,#5b6b66); margin:14px 0 6px;
}
.act-titulo:first-child{ margin-top:0; }
.act-tabla{ width:100%; border-collapse:collapse; font-size:13px; }
.act-tabla th{
  text-align:left; font-size:10px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--med-ink-soft,#5b6b66); padding:6px 8px; border-bottom:1px solid var(--med-verde-100,#DCE9E4);
}
.act-tabla td{ padding:6px 8px; border-bottom:1px solid #f1f5f9; }
.act-tabla td:nth-child(2), .act-tabla td:nth-child(3){ font-variant-numeric:tabular-nums; }
/* Una semana sin mover nada es el dato que se está buscando: se marca, no se esconde. */
.act-inactivo td{ color:var(--med-ink-soft,#5b6b66); }
.act-inactivo td:nth-child(2){ color:var(--med-naranja,#F86000); font-weight:700; }
.act-nota{ font-size:11px; color:var(--med-ink-soft,#5b6b66); margin:8px 0 0; line-height:1.5; }
.act-lista{ list-style:none; margin:0; padding:0; font-size:13px; }
.act-lista li{ padding:6px 0; border-bottom:1px solid #f1f5f9; line-height:1.45; }
.act-cuando{
  display:inline-block; min-width:150px; font-variant-numeric:tabular-nums;
  color:var(--med-ink-soft,#5b6b66); font-size:11px;
}
@media (max-width:768px){
  .act-cuando{ display:block; min-width:0; }
}

/* ===================== COMENTARIOS POR PENDIENTE (01/09/2026) =============
   Decisión de Julio: la conversación va pegada al pendiente, no en una sala de chat.
   Sin hilos anidados: una sola narración cronológica, que es lo que sirve de respaldo. */
.cm-caja{margin-top:14px;padding-top:12px;border-top:1px solid var(--med-verde-100,#DCE9E4)}
.cm-titulo{font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;
  color:var(--med-ink-soft,#5b6b66);margin-bottom:10px;display:flex;align-items:center;gap:8px}
.cm-vacio{font-size:12px;color:var(--med-ink-soft,#5b6b66);padding:4px 0}
.cm-item{display:flex;gap:9px;padding:9px 0;border-bottom:1px solid #eef2f1}
.cm-item:last-of-type{border-bottom:none}
.cm-av{flex:0 0 auto;width:28px;height:28px;border-radius:9999px;display:flex;align-items:center;
  justify-content:center;font-size:10px;font-weight:700;background:var(--med-verde-100,#DCE9E4);
  color:var(--med-verde-900,#18352F)}
/* Quien contesta desde afuera del portal (paso futuro: Jorge por link firmado) se
   distingue del equipo: en un registro, de dónde vino el dato importa. */
.cm-av--fuera{background:#FBE6D8;color:#993C1D}
.cm-cuerpo{flex:1;min-width:0}
.cm-meta{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.cm-quien{font-weight:600;font-size:13px;color:var(--med-verde-900,#18352F)}
.cm-cuando{font-size:11px;color:var(--med-ink-soft,#5b6b66);font-variant-numeric:tabular-nums}
/* Un comentario corregido lo dice. Sin esta marca, la ventana de 5 minutos sería un
   agujero para suavizar lo que uno escribió. */
.cm-editado{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;
  background:#f1f5f9;color:#64748b;border-radius:4px;padding:1px 5px}
.cm-texto{font-size:13px;line-height:1.5;color:#334155;margin-top:2px;overflow-wrap:anywhere}
.cm-mencion{background:#FAEEDA;color:#854F0B;border-radius:4px;padding:0 3px;font-weight:600}
.cm-acciones{display:flex;gap:10px;margin-top:4px}
.cm-accion{background:none;border:none;padding:0;font:inherit;font-size:11px;font-weight:600;
  color:var(--med-verde-600,#2f6f5e);cursor:pointer}
.cm-accion:hover{text-decoration:underline}
.cm-escribir{display:flex;gap:8px;margin-top:10px;position:relative}
/* `position:relative` no es decorativo: la lista de @menciones es `position:absolute;
   bottom:100%` y se cuelga de este contenedor cuando el campo vive en la ventana del
   pendiente. Sin un ancestro posicionado se anclaba a `.vent-velo` y se dibujaba 72 px
   ARRIBA del borde de la pantalla: la lista existía y nadie la veía. En el panel viejo
   no pasaba porque colgaba de `.cm-drawer-pie`, que sí es relative. */
.cm-escribir input{flex:1;padding:8px 10px;border:1px solid #e2e8f0;border-radius:8px;
  font:inherit;font-size:13px}
.cm-escribir input:focus{outline:none;border-color:var(--med-verde-500,#3E7C5A);
  box-shadow:0 0 0 2px rgba(62,124,90,.15)}
.cm-editor{width:100%;padding:5px 8px;border:1px solid var(--med-verde-500,#3E7C5A);
  border-radius:6px;font:inherit;font-size:13px}
.cm-aviso{font-size:11px;color:var(--med-ink-soft,#5b6b66);margin-top:7px;line-height:1.45}

/* El contador en la fila cerrada. Sin esto nadie abre 25 paneles a ver si hay algo. */
.cm-chip-fila{background:var(--med-verde-100,#DCE9E4);color:var(--med-verde-900,#18352F);
  border-radius:9999px;padding:1px 7px;font-size:11px;font-weight:600;margin-left:6px;
  white-space:nowrap;vertical-align:middle}
.cm-chip-fila.hay{background:var(--med-naranja,#F86000);color:#fff}
/* Si te mencionaron, el chip de la barra deja de ser informativo y pasa a ser un pedido. */
#chipComentarios.cm-chip-mencion{background:var(--med-naranja,#F86000)!important;
  color:#fff!important;border-color:#d95400!important}

/* Panel de novedades */
.nov-item{padding:11px 0;border-bottom:1px solid #f1f5f9}
.nov-item:last-child{border-bottom:none}
.nov-mencion{background:#FFFDF7;margin-left:-16px;margin-right:-16px;padding-left:14px;
  padding-right:16px;border-left:2px solid var(--med-naranja,#F86000)}
.nov-donde{display:inline-block;margin-top:5px;background:none;border:none;padding:0;
  font:inherit;font-size:11px;font-weight:600;color:var(--med-verde-600,#2f6f5e);cursor:pointer}
.nov-donde:hover{text-decoration:underline}
.cm-para{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;
  background:#FAEEDA;color:#854F0B;border-radius:4px;padding:1px 6px}

/* Detalle de cada línea del historial (01/09/2026). «Editó un pendiente» solo no dice
   nada; el dato ya estaba en el audit log y solo faltaba leerlo. */
.act-detalle{
  background:var(--med-verde-100,#DCE9E4); color:var(--med-verde-900,#18352F);
  border-radius:4px; padding:1px 6px; font-size:11px; font-weight:600;
}
.act-sobre{
  font-size:11px; color:var(--med-ink-soft,#5b6b66); margin-top:2px;
  padding-left:150px; line-height:1.4;
}
@media (max-width:768px){ .act-sobre{ padding-left:0 } }

/* ===================== MODO COMPACTO DE LA TABLA (01/09/2026) =============
   Julio: «la caja de pendientes solo muestra 4 pendientes, la página se siente
   apretada». Medido en 1440x820: la fila promediaba 73 px (59-84, desparejas) y entraban
   3. Con esto la fila queda en 37 px, pareja, y entran 7.

   El hallazgo que ordenó las prioridades: recortar TODO el encabezado da una sola fila
   más (de 7 a 8). El alto de la fila es el que manda, no el cromo.

   Cuelga de `.filas-compactas` en el <body> y está APAGADO por defecto: se prende desde
   el menú ⋯. Sacar la clase revierte el modo entero sin tocar nada más — la misma
   estrategia que `med-v2` para el reskin del PR #52.

   Qué se pierde y dónde se recupera: el texto largo se corta con «…» (se ve entero al
   abrir el pendiente y en el tooltip de la fila) y los badges 😴/🔺 quedan como icono
   (el texto sigue en su tooltip). Ningún dato desaparece. */


/* ⚠️ TODO adentro de una media query de escritorio. Abajo de 768 px la fila ya es una
   tarjeta (PR #85) y estas reglas la romperían. Acotarlo por estructura y no por
   excepción es lo que pide el test «todo lo de tarjetas vive dentro de una media query»:
   una regla que toca .celda-texto suelta le cambia la tabla a la otra vista. */
@media (min-width:769px){
/* El texto y la categoría comparten renglón: el texto cede, la categoría no. */
  .filas-compactas #tbody .celda-texto .min-w-0{
    display:flex !important; align-items:baseline; gap:8px; min-width:0;
  }
  .filas-compactas #tbody .celda-texto .item-text{
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
    flex:1 1 auto; min-width:0; line-height:1.35;
  }
  .filas-compactas #tbody .celda-texto .min-w-0 > .text-xs{
    margin-top:0 !important; flex:0 0 auto; white-space:nowrap; font-size:10px; opacity:.75;
  }
  .filas-compactas #tbody .celda-texto > .flex{ align-items:center !important; gap:6px !important; }

  /* Los badges pasan a icono. El texto queda en el tooltip, no se pierde. */
  .filas-compactas #tbody .celda-texto .item-text .inline-block{
    font-size:0 !important; padding:1px 2px !important; vertical-align:middle; border-radius:4px;
  }
  .filas-compactas #tbody .celda-texto .item-text .inline-block::first-letter{ font-size:12px !important; }

  /* Menos aire, y los controles a la altura del texto. */
  .filas-compactas #tbody td{ padding-top:4px !important; padding-bottom:4px !important; }
  .filas-compactas #tbody select,
  .filas-compactas #tbody input[type="date"]{
    padding:1px 4px !important; font-size:12px !important; height:22px !important;
  }
  .filas-compactas #tbody .celda-dato > div{ line-height:1.2 !important; }
  /* «Modificado»: quién y cuándo en un solo renglón. */
  .filas-compactas #tbody td.text-xs > div{
    display:flex; gap:6px; align-items:baseline; white-space:nowrap;
  }
}

/* ===================== PANEL LATERAL DE COMENTARIOS (01/09/2026) ==========
   Los comentarios vivían adentro del panel desplegable de la fila. Medido a 1440x820 con
   el modo compacto: ese panel mide 991 px —más que la ventana— y tapa el equivalente a 28
   filas. Julio: «el chip quita demasiado espacio cuando se despliega, ¿no es mejor una
   ventana flotante?».

   TAPA, no empuja: las columnas suman ~1.549 px y a 1440 entran justas, así que angostar
   la tabla genera scroll horizontal (probado). Para que el panel no tape las fechas,
   mientras está abierto se esconden «Solicitada» y «Modificado» —las mismas que salieron
   del celular en el PR #85: una es histórico, la otra auditoría— y la columna de texto
   cede. No se pierde nada: el nombre completo del pendiente está en la cabecera del
   panel, que es de lo que se está hablando. */
.cm-drawer{
  position:fixed; top:0; right:0; bottom:0; width:360px; z-index:60;
  background:#fff; border-left:1px solid var(--med-verde-100,#DCE9E4);
  box-shadow:-14px 0 34px rgba(16,32,28,.13);
  display:flex; flex-direction:column;
}
.cm-drawer-head{ padding:12px 14px; border-bottom:1px solid #eef2f1; }
.cm-drawer-sobre{
  font-size:10px; font-weight:700; letter-spacing:.07em; text-transform:uppercase;
  color:var(--med-ink-soft,#5b6b66); margin-bottom:3px;
}
.cm-drawer-titulo{
  font-size:14px; font-weight:600; color:var(--med-verde-900,#18352F); line-height:1.35;
  display:flex; justify-content:space-between; gap:10px; align-items:flex-start;
}
.cm-drawer-x{
  background:none; border:none; font-size:20px; line-height:1; cursor:pointer;
  color:#94a3b8; flex:0 0 auto; padding:0 2px;
}
.cm-drawer-x:hover{ color:var(--med-verde-900,#18352F); }
.cm-drawer-cuerpo{ flex:1; overflow-y:auto; padding:4px 14px; }
.cm-drawer-cuerpo .cm-caja{ margin-top:0; padding-top:0; border-top:none; }
.cm-drawer-cuerpo .cm-titulo{ margin-bottom:6px; }
.cm-drawer-pie{ padding:10px 14px; border-top:1px solid #eef2f1; background:#fbfdfc; }
.cm-drawer-pie .cm-escribir{ margin-top:0; }

/* La fila cuya conversación está abierta, marcada para no perderla de vista. */
.fila-abierta{ box-shadow:inset 3px 0 0 var(--med-naranja,#F86000); }
.med-v2 .fila-abierta > td{ background:#FFFDF7 !important; }

/* El chip es el botón que abre la conversación. Está siempre: si solo apareciera cuando
   ya hay comentarios, no habría por dónde escribir el primero. */
.cm-chip-fila{ border:none; font:inherit; cursor:pointer; }
.cm-chip-fila.vacio{
  background:transparent; color:#cbd5e1; padding:1px 4px;
}
.cm-chip-fila.vacio:hover{ background:var(--med-verde-100,#DCE9E4); color:var(--med-verde-900,#18352F); }

@media (min-width:769px){
  /* Mientras la conversación está abierta, la tabla cede lo que no se está mirando. */
  body.con-drawer .celda-solo-escritorio{ display:none !important; }
  body.con-drawer .tabla-wrap table{ width:auto !important; }
  body.con-drawer #tbody .celda-texto{ max-width:330px !important; }
  body.con-drawer thead th:nth-child(2){ width:330px !important; }
}
@media (max-width:768px){
  /* En el teléfono no hay lugar para un costado: ocupa la pantalla. */
  .cm-drawer{ width:100%; border-left:none; }
}

/* Autocompletar @menciones. Julio: «si presiono @ no autocompleta ningún nombre».
   Ofrece SOLO a quien el backend reconoce como mención (users.json): sugerir a alguien
   que después no cuenta sería mentirle al que escribe y al mencionado. */
.cm-menciones{
  position:absolute; bottom:100%; left:14px; right:14px; margin-bottom:6px; z-index:5;
  background:#fff; border:1px solid var(--med-verde-100,#DCE9E4); border-radius:10px;
  box-shadow:0 8px 22px rgba(16,32,28,.14); overflow:hidden; max-height:210px; overflow-y:auto;
}
.cm-drawer-pie{ position:relative; }
.cm-mencion-op{
  display:flex; align-items:baseline; gap:8px; width:100%; text-align:left;
  background:none; border:none; font:inherit; padding:7px 11px; cursor:pointer;
}
.cm-mencion-op:hover, .cm-mencion-op.elegida{ background:var(--med-verde-100,#DCE9E4); }
.cm-mencion-clave{ font-size:12px; font-weight:700; color:var(--med-verde-900,#18352F); }
.cm-mencion-nombre{ font-size:11px; color:var(--med-ink-soft,#5b6b66); }

/* El chip de menciones rebota unos segundos y se calma. Movimiento que no para deja de
   ser un aviso y pasa a ser una molestia que se aprende a ignorar. */
.cm-chip-rebota{ animation: cm-rebote .6s ease-in-out 0s 6; }
@keyframes cm-rebote{
  0%,100%{ transform:translateY(0); }
  25%{ transform:translateY(-5px); }
  50%{ transform:translateY(0); }
  75%{ transform:translateY(-2px); }
}
/* El aviso NO puede depender del movimiento: para quien pidió menos movimiento queda el
   naranja, que es la señal de verdad. */
@media (prefers-reduced-motion: reduce){
  .cm-chip-rebota{ animation:none; }
}

/* ===================== LA VENTANA DEL PENDIENTE (02/09/2026) ==============
   Julio: «por qué a un lado y no al frente, para que sea bien legible todo cómodo» y
   «tenemos un editor de texto y un editor de pendiente, deberíamos usar solo uno».

   Reemplaza al panel que se desplegaba abajo de la fila. Medido a 1440x820 con el modo
   compacto: ese panel medía 991 px —más que la ventana del navegador— y tapaba el
   equivalente a 28 filas.

   Tres pestañas: Ficha (lo que se toca) · Conversación (lo que se lee y escribe) ·
   Registro (lo que se consulta cuando hay que probar algo). Apiladas sumaban 991 px;
   separadas, cada una entra sin scrollear. */
.vent-velo{
  position:fixed; inset:0; z-index:80; background:rgba(16,32,28,.42);
  display:flex; align-items:center; justify-content:center; padding:24px;
}
.vent{
  width:760px; max-width:100%; max-height:86vh; background:#fff; border-radius:14px;
  box-shadow:0 24px 60px rgba(16,32,28,.34); display:flex; flex-direction:column; overflow:hidden;
}
.vent-head{ padding:14px 18px 0; border-bottom:1px solid #eef2f1; }
.vent-arriba{ display:flex; align-items:center; gap:10px; }
.vent-cat{
  font-size:11px; font-weight:700; color:var(--med-verde-900,#18352F);
  background:var(--med-verde-100,#DCE9E4); border-radius:9999px; padding:3px 10px;
}
.vent-x{ background:none; border:none; font-size:23px; line-height:1; color:#94a3b8; cursor:pointer; }
.vent-x:hover{ color:var(--med-verde-900,#18352F); }
/* El título se edita acá: el ✎ de la fila se sacó, para que haya un solo editor. */
.vent-titulo{
  width:100%; font-size:17px; font-weight:600; color:var(--med-verde-900,#18352F);
  border:1px solid transparent; border-radius:7px; padding:6px 8px; margin:9px 0 0;
  font-family:inherit; background:#fff;
}
.vent-titulo:hover:not(:disabled){ border-color:#e2e8f0; }
.vent-titulo:focus{ outline:none; border-color:var(--med-verde-500,#3E7C5A);
  box-shadow:0 0 0 2px rgba(62,124,90,.15); }
.vent-titulo:disabled{ background:transparent; color:var(--med-verde-900,#18352F); }
.vent-ayuda{ font-size:10px; color:#94a3b8; padding:0 8px; }
.vent-meta{ display:flex; gap:15px; flex-wrap:wrap; margin:10px 0 0; font-size:11px;
  color:var(--med-ink-soft,#5b6b66); padding:0 8px; }
.vent-meta b{ color:var(--med-verde-900,#18352F); font-weight:600; }
.vent-meta .alerta b{ color:var(--med-naranja,#F86000); }
.vent-tabs{ display:flex; gap:2px; margin-top:12px; }
.vt{ padding:8px 14px; font-size:12px; font-weight:600; border:none; background:none;
  color:var(--med-ink-soft,#5b6b66); cursor:pointer; border-bottom:2px solid transparent;
  font-family:inherit; }
.vt.activa{ color:var(--med-verde-900,#18352F); border-bottom-color:var(--med-naranja,#F86000); }
.vt .n{ background:var(--med-verde-100,#DCE9E4); border-radius:9999px; padding:0 6px;
  font-size:10px; margin-left:5px; }
.vent-cuerpo{ flex:1; overflow-y:auto; padding:15px 18px; }
.vent-pie{ padding:11px 18px; border-top:1px solid #eef2f1; background:#fbfdfc;
  display:flex; gap:8px; justify-content:flex-end; }
.vent-pie .cm-escribir{ margin-top:0; width:100%; }
/* ⚠️ `display:flex` le gana al atributo [hidden] y a `.hidden` de Tailwind. Es la misma
   trampa del PR #52, que mostró botones que dependían del rol. Se declara explícito. */
.vent-pie[hidden], .vent-cuerpo[hidden]{ display:none !important; }
/* Los bloques del detalle, ya sin el panel desplegable que los envolvía. */
.vent-cuerpo .detail-panel{ background:transparent; border:none; padding:0; }
@media (max-width:768px){
  .vent-velo{ padding:0; }
  .vent{ width:100%; max-height:100%; border-radius:0; }
}
