
:root{
  color-scheme: light;
  --bg:#f0f4f8; --surface:#ffffff; --surface2:#f8fafc;
  --text:#1a2332; --text2:#475569; --text3:#94a3b8; --border:#e2e8f0;
  --primary:#2563eb;
  --hdr:linear-gradient(135deg,#1e3a5f 0%,#1d4ed8 100%);
  --shadow:0 1px 3px rgba(0,0,0,.07); --shadow-md:0 3px 10px rgba(0,0,0,.10);
}
[data-theme="dark"]{
  color-scheme: dark;
  --bg:#0f172a; --surface:#1e293b; --surface2:#263347;
  --text:#f1f5f9; --text2:#94a3b8; --text3:#64748b; --border:#334155;
  --primary:#3b82f6;
  --hdr:linear-gradient(135deg,#0f172a 0%,#1e3a5f 100%);
  --shadow:0 1px 3px rgba(0,0,0,.35); --shadow-md:0 3px 10px rgba(0,0,0,.4);
}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  background:var(--bg);color:var(--text);font-size:14px;min-height:100vh;transition:background .25s,color .25s;}
/* Javi, 2026-08-26: "cuando muevo el scroll del mouse se mueve la pantalla de detrás" (con
   #taskModal u otro <dialog> abierto). showModal() hace inert al resto de contenido para foco/
   click, pero NO bloquea que la rueda del ratón siga haciendo scroll de <body> si es más alto
   que el viewport (típico en esta app, listado largo de tareas) -- el evento wheel llega a
   document/body igual, sean o no inert los elementos de alrededor. Fix de una sola regla, vale
   para TODOS los <dialog> del archivo (taskModal, burndownModal, histoModal, dedicListModal,
   commentHistoryModal, etc.) sin tener que tocar cada función de apertura/cierre:
   mientras haya algún <dialog open>, se bloquea el scroll de body entero. */
body:has(dialog[open]){overflow:hidden;}

.header{background:var(--hdr);color:#fff;padding:10px 20px;display:flex;align-items:center;justify-content:space-between;box-shadow:0 2px 8px rgba(30,58,95,.3);}
.hdr-left{display:flex;align-items:center;gap:12px;}
.avatar{width:42px;height:42px;border-radius:50%;background:rgba(255,255,255,.2);border:2px solid rgba(255,255,255,.5);
  display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:800;color:#fff;flex-shrink:0;letter-spacing:.5px;}
.hdr-title h1{font-size:16px;font-weight:700;letter-spacing:-.3px;}
.hdr-title .sub{font-size:11px;opacity:.7;margin-top:1px;}
.hdr-right{display:flex;gap:8px;align-items:center;}
.btn-theme,.btn-refresh{border:none;padding:6px 13px;border-radius:6px;font-size:12px;font-weight:600;cursor:pointer;font-family:inherit;transition:opacity .15s;}
.btn-theme{background:rgba(255,255,255,.15);color:#fff;border:1px solid rgba(255,255,255,.25);}
.btn-theme:hover{background:rgba(255,255,255,.25);}
.btn-refresh{background:#fff;color:#1e3a5f;}
.btn-refresh:hover:not(:disabled){background:#e8f0ff;}
.btn-refresh:disabled{opacity:.5;cursor:not-allowed;}
/* Clic en el avatar de cabecera (a petición explícita de Javi, 2026-07-26):
   - Si CURRENT_USER_ADMIN: abre el conmutador REQ-10 ⇄ REQ-17 con el enlace a "/admin/" (Panel
     de administración) — ver actualizarSwitcherAdmin()/toggleAdminSwitcher().
   - Si NO es admin (cualquier Team Member): abre el modal de autoservicio "Foto de perfil" —
     ver onAvatarClick()/openMiFotoModal(). El avatar es clicable para todo el mundo, por eso el
     cursor:pointer ya no depende de la clase is-admin (se deja la clase por si se necesita en el
     futuro, pero ya no controla el cursor). */
.avatar-wrap{position:relative;cursor:pointer;}
.user-av{width:36px;height:36px;border-radius:50%;background:var(--surface2);
  display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:800;
  color:var(--primary);flex-shrink:0;}
/* Miniatura de la persona asignada en tarjetas de tarea (tareas Nº 64 y Nº 65, a petición
   explícita de Javi, 2026-08-04): Bandeja de entrada (taskCardHtml, opts.bandejaActions) y
   tablero de "Mis Proyectos" (renderKanban). Fallback sin foto = iniciales en blanco sobre
   var(--primary) (ajuste 2026-08-04, a petición explícita de Javi: antes gris neutro), igual
   para todas las personas (sin color por persona, a diferencia de PROJECT_COLORS). El fondo solo
   se ve si la persona no tiene foto -- con foto, el <img> cubre el círculo entero (ver regla
   siguiente). Tamaño 24px (ajuste 2026-08-04, a petición explícita de Javi: antes 18px). Ver
   avatarMiniHtml(). */
.mini-avatar{width:24px;height:24px;border-radius:50%;background:var(--primary);color:#fff;
  display:inline-flex;align-items:center;justify-content:center;font-size:11px;font-weight:800;
  flex-shrink:0;overflow:hidden;vertical-align:middle;}
.mini-avatar img{width:100%;height:100%;object-fit:cover;border-radius:50%;}
.avatar-switcher{position:absolute;top:calc(100% + 8px);left:0;background:var(--surface);color:var(--text);
  border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.18);padding:6px;min-width:200px;z-index:50;}
.avatar-switcher a{display:block;padding:8px 10px;border-radius:6px;font-size:12.5px;font-weight:600;
  color:var(--text);text-decoration:none;white-space:nowrap;}
.avatar-switcher a:hover{background:var(--surface2);}
.hdr-user{font-size:12px;opacity:.85;margin-right:2px;}
.last-upd{font-size:10px;opacity:.6;}

/* ── PANTALLA DE LOGIN (Supabase Auth) — branding SGP-Lenfox sobre la estética de lenfox.com ── */
.auth-screen{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px;
  background:linear-gradient(rgba(15,23,42,.55),rgba(15,23,42,.72)),
    url("https://i0.wp.com/lenfox.com/wp-content/uploads/2015/01/pexels-photo-3182781.jpeg?fit=1920%2C1280&ssl=1") center/cover no-repeat;}
.auth-card{width:min(420px,100%);background:rgba(255,255,255,.97);border-radius:14px;box-shadow:0 20px 60px rgba(0,0,0,.35);padding:34px 32px;}
.auth-logo{display:block;height:40px;margin:0 auto 18px;}
.auth-card h1{font-size:19px;margin:0 0 6px;color:#1a2332;text-align:center;font-weight:800;}
.auth-sub{font-size:12.5px;color:#64748b;margin:0 0 20px;line-height:1.5;text-align:center;}
.auth-card .form-group{margin-bottom:12px;}
.auth-card .form-control{padding:10px 13px;font-size:14px;}
.auth-toggle{text-align:center;margin-top:14px;font-size:12.5px;}
.auth-toggle a{color:var(--primary);text-decoration:none;cursor:pointer;}
.auth-toggle a:hover{text-decoration:underline;}

.scope-banner{background:#fffbeb;color:#92400e;font-size:11px;padding:6px 20px;border-bottom:1px solid #fde68a;}
[data-theme="dark"] .scope-banner{background:#3a2e10;color:#fbbf24;border-color:#5c4a10;}

.filters{background:var(--surface);padding:9px 20px;border-bottom:1px solid var(--border);display:flex;gap:10px;align-items:center;flex-wrap:wrap;}
.filter-group{display:flex;align-items:center;gap:6px;}
.filter-group label{font-size:11px;font-weight:600;color:var(--text2);}
select,input[type=number],input[type=text]{
  border:1px solid var(--border);border-radius:6px;padding:5px 9px;font-size:12px;
  background:var(--surface);color:var(--text);font-family:inherit;transition:border-color .15s,background .25s,color .25s;}
select:focus,input:focus{outline:none;border-color:var(--primary);box-shadow:0 0 0 3px rgba(37,99,235,.12);}
.btn-clear{border:none;background:transparent;color:var(--primary);font-size:11px;font-weight:600;cursor:pointer;text-decoration:underline;}

.search-bar{background:var(--surface);padding:9px 20px;border-bottom:1px solid var(--border);
  display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;}
.search-bar input{width:340px;max-width:100%;padding:7px 12px;font-size:13px;}
.search-bar-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
/* Botón redondo para limpiar la caja de búsqueda por texto (a petición explícita de Javi) */
.search-box-wrap{position:relative;display:inline-flex;align-items:center;}
.search-box-wrap input{padding-right:28px !important;}
.search-clear-btn{position:absolute;right:6px;top:50%;transform:translateY(-50%);
  width:18px;height:18px;border-radius:50%;border:none;background:var(--border);color:var(--text2);
  font-size:10px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;}
.search-clear-btn:hover{background:#cbd5e1;color:var(--text);}

.bulk-bar{display:flex;align-items:center;flex-wrap:wrap;gap:12px;background:#eff6ff;border:1px solid #bfdbfe;
  color:#1e3a8a;padding:8px 14px;border-radius:8px;margin:0 20px 10px;font-size:12.5px;font-weight:600;}
[data-theme="dark"] .bulk-bar{background:#1e293b;border-color:#334155;color:#93c5fd;}
tbody tr td.sel-cell, thead th:first-child{text-align:center;}
input.row-sel{width:15px;height:15px;cursor:pointer;}
.summary-row{display:grid;grid-template-columns:repeat(9,1fr);gap:10px;padding:14px 20px 4px;}
.sum-card{background:var(--surface);border-radius:10px;padding:13px 15px;box-shadow:var(--shadow);
  transition:all .18s;cursor:pointer;border:2px solid transparent;user-select:none;position:relative;overflow:hidden;}
.sum-card::after{content:'';position:absolute;bottom:0;right:0;width:90px;height:67px;
  opacity:.15;pointer-events:none;z-index:0;
  background:url("data:image/svg+xml,%3Csvg viewBox='0 0 220 160' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='130' cy='95' r='48' fill='%232563eb'/%3E%3Ccircle cx='62' cy='115' r='30' fill='%232563eb'/%3E%3Ccircle cx='180' cy='42' r='24' fill='%232563eb'/%3E%3Ccircle cx='28' cy='42' r='19' fill='%232563eb'/%3E%3Ccircle cx='162' cy='118' r='17' fill='%232563eb'/%3E%3Ccircle cx='95' cy='28' r='15' fill='%232563eb'/%3E%3Ccircle cx='195' cy='125' r='11' fill='%232563eb'/%3E%3C/svg%3E") no-repeat bottom right/contain;}
.sum-card > *{position:relative;z-index:1;}
.sum-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);}
.sum-card.active-filter{border-color:var(--primary);box-shadow:0 0 0 3px rgba(37,99,235,.15);}
.slabel{font-size:10px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.6px;}
.sval{font-size:26px;font-weight:800;margin-top:2px;line-height:1;}
.ssub{font-size:11px;color:var(--text3);margin-top:3px;}

/* Variante compacta de .sum-card para chips fuera de la fila de resumen (p.ej. junto al buscador) */
.sum-card-mini{padding:6px 12px;display:flex;align-items:center;gap:7px;flex:none;border-radius:8px;}
.sum-card-mini::after{display:none;}
.sum-card-mini .slabel{font-size:9px;}
.sum-card-mini .sval{font-size:16px;margin-top:0;line-height:1;}

.content{padding:12px 20px 60px;}
.tl-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;}
.section-title{font-size:10px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.6px;}

/* ── PESTAÑA "MIS TAREAS" (fusión de REQ-8) ─── */
#summaryRowMT{grid-template-columns:repeat(3,1fr);flex:1;margin:0;padding:0;align-content:start;}
.task-card{background:var(--surface);border-radius:8px;padding:10px 13px;
  margin-bottom:7px;box-shadow:var(--shadow);cursor:pointer;
  border-left:4px solid transparent;transition:border-color .12s,box-shadow .12s,background .25s;}
.task-card:hover{box-shadow:var(--shadow-md);}
.tc-top{display:flex;align-items:center;gap:10px;}
.rag-dot{width:9px;height:9px;border-radius:50%;flex-shrink:0;}
.task-info{flex:1;min-width:0;}
.task-name{font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--text);}
.task-code-badge{color:var(--primary);font-weight:800;margin-right:5px;}
.kanban-code-badge{color:var(--primary);font-weight:800;margin-right:4px;}
.task-meta{font-size:11px;color:var(--text2);margin-top:3px;display:flex;gap:5px;align-items:center;flex-wrap:wrap;}
.tc-comment{font-size:11px;color:var(--text3);margin-top:5px;padding-top:5px;
  border-top:1px solid var(--border);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  font-style:italic;}
.tc-comment.loading{color:var(--border);}
.mt-proj-chip{padding:1px 7px;border-radius:4px;font-size:10px;font-weight:600;background:var(--surface2);color:var(--text2);}
/* Nº 125 (2ª ronda, 2026-08-27, a peticion explicita de Javi): el nombre del proyecto en el
   modal de detalle de tarea se alinea al centro (antes a la izquierda por defecto). */
#mProyecto{text-align:center;}
/* Rosco "Tareas por proyecto" (CC-035) + tarjetas de indicadores en la misma fila (CC-041, a
   petición explícita de Javi: el rosco a toda anchura ocupaba demasiado espacio vertical). */
.mt-top-row{display:flex;gap:14px;align-items:stretch;margin-bottom:14px;}
.pie-card{margin:0;flex:0 0 230px;}
.pie-wrap{height:108px;position:relative;}
.pie-hint{font-size:10px;color:var(--text3);text-align:center;margin-top:5px;}
.active-project-badge{display:inline-block;background:var(--primary);color:#fff;
  padding:2px 8px;border-radius:12px;font-size:10px;font-weight:600;margin-left:6px;cursor:pointer;}

/* ── TABLE + WATERMARK ────────────────── */
.table-wrap{
  background:var(--surface);border-radius:10px;box-shadow:var(--shadow);overflow-x:auto;overflow-y:hidden;
  position:relative;-webkit-overflow-scrolling:touch;
}
.table-watermark{
  position:absolute;inset:0;pointer-events:none;z-index:0;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='200' viewBox='0 0 260 200'%3E%3Cg fill='%232563eb' fill-opacity='0.10'%3E%3Ccircle cx='150' cy='110' r='52'/%3E%3Ccircle cx='70' cy='140' r='32'/%3E%3Ccircle cx='210' cy='50' r='26'/%3E%3Ccircle cx='30' cy='40' r='20'/%3E%3Ccircle cx='190' cy='150' r='18'/%3E%3Ccircle cx='110' cy='25' r='16'/%3E%3Ccircle cx='235' cy='150' r='12'/%3E%3C/g%3E%3C/svg%3E");
  background-repeat:repeat; background-size:260px 200px; opacity:.35;
}
[data-theme="dark"] .table-watermark{ opacity:.18; }
table{width:max-content;min-width:100%;border-collapse:collapse;position:relative;z-index:1;font-size:12.5px;}
thead th{position:sticky;top:0;background:var(--surface2);backdrop-filter:blur(2px);
  text-align:left;padding:9px 12px;font-size:10px;font-weight:700;color:var(--text3);
  text-transform:uppercase;letter-spacing:.5px;border-bottom:1px solid var(--border);white-space:nowrap;}
tbody tr{cursor:pointer;transition:background .12s;}
tbody tr:nth-child(even){background:rgba(37,99,235,.055);}
[data-theme="dark"] tbody tr:nth-child(even){background:rgba(59,130,246,.10);}
tbody tr:hover{background:rgba(37,99,235,.12);}
tbody tr.row-highlight{animation:rowFlash 2.4s ease;}
@keyframes rowFlash{0%{background:#fde68a;}100%{background:transparent;}}

thead th.sortable-th{cursor:pointer;user-select:none;white-space:nowrap;}
thead th.sortable-th:hover{background:rgba(37,99,235,.14);}
thead th.sortable-th::after{content:'';display:inline-block;width:9px;margin-left:3px;opacity:.35;font-size:9px;}
thead th.sortable-th.sort-asc::after{content:'▲';opacity:.9;}
thead th.sortable-th.sort-desc::after{content:'▼';opacity:.9;}

.table-pagination{display:flex;align-items:center;justify-content:center;gap:6px;padding:12px 20px;
  border-top:1px solid var(--border);background:var(--surface);flex-wrap:wrap;}
.table-pagination .pg-info{font-size:11.5px;color:var(--text2);margin-right:10px;}
.table-pagination button{border:1px solid var(--border);background:var(--surface);color:var(--text2);
  border-radius:6px;padding:5px 10px;font-size:12px;font-weight:600;cursor:pointer;font-family:inherit;min-width:30px;}
.table-pagination button:hover:not(:disabled){background:var(--surface2);border-color:var(--primary);}
.table-pagination button:disabled{opacity:.4;cursor:not-allowed;}
.table-pagination button.pg-active{background:var(--primary);border-color:var(--primary);color:#fff;}
tbody td{padding:9px 12px;border-bottom:1px solid var(--border);vertical-align:middle;color:var(--text);}
tbody tr:last-child td{border-bottom:none;}
td.code{font-weight:800;color:var(--primary);white-space:nowrap;}
td.name{font-weight:600;max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
tfoot td{padding:10px 12px;border-top:2px solid var(--border);background:var(--surface2);
  font-weight:800;color:var(--text);position:relative;z-index:1;}
/* Backlog (Mis Tareas, 2026-07-30): esta tabla no tiene tfoot (no hay horas que totalizar,
   a diferencia de la de "Mis Proyectos") -- el tfoot de esa otra tabla actúa sin querer como
   "colchón" para que la barra de scroll horizontal (overlay en macOS/iOS, ver
   -webkit-overflow-scrolling:touch en .table-wrap) no se monte encima de la última fila de datos
   reales. Bug reportado por Javi: al filtrar por nombre y quedar pocas filas, el scroll horizontal
   se solapaba con la última fila. Mismo colchón que el tfoot, sin fabricar un tfoot falso. */
#mtVistaBacklog .table-wrap{ padding-bottom: 14px; }

/* Notas (Mis Tareas, REQ-23, 2026-07-31): espacio personal tipo checklist, privado por usuario
   (tabla notas_personales, RLS por usuario_id -- ver migración crear_notas_personales). Recordatorio
   opcional por ítem; el aviso de "vencido" es descartable (recordatorio_visto), no se repite solo
   como al pasar de página. Sin arrastre/orden manual: MVP con orden automático (pendientes primero
   por fecha de recordatorio, completadas al final) -- decisiones cerradas con Javi el 2026-07-31. */
.notas-add-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:14px;}
.notas-add-row input[type="text"]{flex:1;min-width:220px;padding:8px 12px;border:1px solid var(--border);
  border-radius:6px;background:var(--surface);color:var(--text);font-size:13px;}
.notas-add-row input[type="datetime-local"]{padding:7px 10px;border:1px solid var(--border);
  border-radius:6px;background:var(--surface);color:var(--text);font-size:13px;}
.nota-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--border);
  border-radius:8px;background:var(--surface);margin-bottom:8px;}
.nota-item.completado{opacity:.6;}
.nota-item.completado .nota-texto{text-decoration:line-through;color:var(--text3);}
.nota-item input[type="checkbox"]{width:16px;height:16px;flex-shrink:0;cursor:pointer;}
.nota-texto{flex:1;color:var(--text);font-size:13px;word-break:break-word;}
.nota-actions{display:flex;gap:6px;flex-shrink:0;}
tfoot td.tf-label{text-align:right;color:var(--text3);font-weight:700;text-transform:uppercase;font-size:10px;letter-spacing:.5px;}

.badge{display:inline-block;padding:2px 7px;border-radius:20px;font-size:10px;font-weight:600;line-height:1.4;white-space:nowrap;}
.tt-badge{display:inline-block;padding:2px 7px;border-radius:5px;font-size:10px;font-weight:700;white-space:nowrap;}

.empty-msg{text-align:center;padding:40px;color:var(--text3);font-size:13px;position:relative;z-index:1;}
.loader{text-align:center;padding:50px 20px;color:var(--text2);}
.spinner{width:26px;height:26px;margin:0 auto 12px;border:3px solid var(--border);border-top-color:var(--primary);
  border-radius:50%;animation:spin .75s linear infinite;}
@keyframes spin{to{transform:rotate(360deg);}}

/* ── PANTALLA DE CARGA INICIAL (CC-042) ──── */
#loadingOverlay{position:fixed;inset:0;z-index:9999;background:#f0f4f8;
  display:flex;align-items:center;justify-content:center;padding:20px;}
.loading-card{max-width:380px;background:#fff;border-radius:14px;box-shadow:0 8px 30px rgba(0,0,0,.12);
  padding:34px 30px;text-align:center;}
.loading-icon{margin-bottom:10px;animation:loadingPulse 1.6s ease-in-out infinite;}
@keyframes loadingPulse{0%,100%{opacity:1;}50%{opacity:.55;}}
.loading-title{font-size:18px;font-weight:800;color:#1a2332;margin-bottom:6px;}
.loading-msg{font-size:13.5px;color:#475569;line-height:1.6;}

/* ── MODAL ─────────────────────────────── */
#taskModal{border:none;border-radius:12px;padding:0;width:min(860px,94vw);height:88vh;max-height:88vh;
  background:var(--surface);color:var(--text);box-shadow:0 20px 60px rgba(0,0,0,.35);overflow:hidden;
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;}
#taskModal[open]{display:flex;flex-direction:column;}
#taskModal::backdrop{background:rgba(0,0,0,.52);backdrop-filter:blur(3px);}

#burndownModal{border:none;border-radius:12px;padding:0;width:min(640px,92vw);
  background:var(--surface);color:var(--text);box-shadow:0 20px 60px rgba(0,0,0,.35);overflow:hidden;
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;}
#burndownModal[open]{display:flex;flex-direction:column;}
#burndownModal::backdrop{background:rgba(0,0,0,.52);backdrop-filter:blur(3px);}

#histoModal{border:none;border-radius:12px;padding:0;width:min(640px,92vw);
  background:var(--surface);color:var(--text);box-shadow:0 20px 60px rgba(0,0,0,.35);overflow:hidden;
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;}
#histoModal[open]{display:flex;flex-direction:column;}
#histoModal::backdrop{background:rgba(0,0,0,.52);backdrop-filter:blur(3px);}

#dedicListModal{border:none;border-radius:12px;padding:0;width:min(640px,92vw);max-height:80vh;
  background:var(--surface);color:var(--text);box-shadow:0 20px 60px rgba(0,0,0,.35);overflow:hidden;
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;}
#dedicListModal[open]{display:flex;flex-direction:column;}
#dedicListModal::backdrop{background:rgba(0,0,0,.6);backdrop-filter:blur(2px);}
#dedicListModal .modal-body{overflow-y:auto;}

#commentHistoryModal{border:none;border-radius:12px;padding:0;width:min(720px,94vw);height:82vh;max-height:82vh;
  background:var(--surface);color:var(--text);box-shadow:0 20px 60px rgba(0,0,0,.35);overflow:hidden;
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;}
#commentHistoryModal[open]{display:flex;flex-direction:column;}
#commentHistoryModal::backdrop{background:rgba(0,0,0,.55);backdrop-filter:blur(3px);}
#commentHistoryModal .modal-body{display:flex;flex-direction:column;overflow:hidden;padding:16px 18px;}
#commentHistoryModal .comments-section{border-top:none;padding:0;position:relative;flex:0 0 auto;}
#commentHistoryModal .comment-history{flex:1 1 auto;max-height:none;overflow-y:auto;margin-top:10px;}

#dedicEditModal{border:none;border-radius:12px;padding:0;width:min(480px,92vw);
  background:var(--surface);color:var(--text);box-shadow:0 20px 60px rgba(0,0,0,.35);overflow:hidden;
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;}
#dedicEditModal[open]{display:flex;flex-direction:column;}
#dedicEditModal::backdrop{background:rgba(0,0,0,.6);backdrop-filter:blur(2px);}

#projectInfoModal{border:none;border-radius:12px;padding:0;width:min(480px,92vw);max-height:88vh;
  background:var(--surface);color:var(--text);box-shadow:0 20px 60px rgba(0,0,0,.35);overflow:hidden;
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;}
#projectInfoModal[open]{display:flex;flex-direction:column;}
#projectInfoModal::backdrop{background:rgba(0,0,0,.52);backdrop-filter:blur(3px);}
#projectInfoModal .modal-body{overflow-y:auto;}

/* Alcance (2026-08-29, ronda de ajustes tras prueba de Javi): #tmpanel-alcance pasa a columna
   flex de altura completa para que el editor aproveche todo el largo del modal disponible, en
   vez de quedarse a min-height:240px con el resto del panel vacío debajo -- toolbar y la fila
   del botón "Guardar Alcance"/feedback quedan flex-shrink:0 (tamaño fijo), el editor es el único
   que crece (flex:1 1 auto) y mantiene su propio scroll interno. */
#tmpanel-alcance.visible{display:flex;flex-direction:column;height:100%;}
.enfoque-toolbar{display:flex;align-items:center;gap:2px;flex-wrap:wrap;padding:6px;background:var(--surface2);
  border:1px solid var(--border);border-bottom:none;border-radius:8px 8px 0 0;flex-shrink:0;}
.enfoque-tbtn{border:none;background:transparent;color:var(--text2);width:28px;height:26px;border-radius:5px;
  cursor:pointer;font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:center;padding:0;}
.enfoque-tbtn:hover{background:rgba(37,99,235,.12);color:var(--primary);}
.enfoque-tsep{width:1px;align-self:stretch;background:var(--border);margin:3px 3px;}
.enfoque-editor{border:1px solid var(--border);border-top:none;border-radius:0 0 8px 8px;
  min-height:240px;flex:1 1 auto;overflow-y:auto;padding:12px 14px;font-size:13px;line-height:1.6;
  color:var(--text);background:var(--surface);}
/* Cuando el toolbar está oculto (solo lectura sin ser colaborador, ver openTaskModal) el editor
   deja de tener el toolbar encima que le daba el borde superior visual -- sin esta clase, el
   recuadro queda "abierto" por arriba (bug reportado por Javi tras probar en el preview). */
.enfoque-editor.enfoque-editor-standalone{border-top:1px solid var(--border);border-radius:8px;}
.enfoque-editor:focus{outline:none;}
.enfoque-editor h1{font-size:19px;margin:10px 0 6px;font-weight:800;}
.enfoque-editor h2{font-size:16px;margin:9px 0 5px;font-weight:800;}
.enfoque-editor h3{font-size:14px;margin:8px 0 4px;font-weight:700;}
.enfoque-editor p{margin:0 0 8px;}
.enfoque-editor ul,.enfoque-editor ol{margin:0 0 8px 20px;padding:0;}
.enfoque-editor li{margin-bottom:3px;}
.enfoque-editor:empty:before{content:attr(data-placeholder);color:var(--text3);}
/* Javi, 2026-09-02: "ahora veo los enlaces, pero no me deja hacer clic en ellos" -- ya se
   puede (ver el listener de document.addEventListener('click', ...) más abajo), pero dentro de
   un contenteditable el cursor por defecto sigue siendo el de texto (I-beam), así que no hay
   ninguna pista visual de que haya un enlace clicable debajo. */
.enfoque-editor a{cursor:pointer;}
/* Javi, 2026-09-02: soporte de bloques de código ```…``` y código en línea `…` en el Alcance
   (ver enfoqueMarkdownToHtml más abajo) -- mismo tratamiento visual que el resto de la app usa
   para contenido de tipo código. */
.enfoque-editor pre{background:var(--surface2);border:1px solid var(--border);border-radius:6px;
  padding:10px 12px;overflow-x:auto;margin:0 0 8px;}
.enfoque-editor pre code{background:none;padding:0;}
.enfoque-editor code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:12px;background:var(--surface2);border-radius:4px;padding:1px 5px;}

#newTaskModal{border:none;border-radius:12px;padding:0;width:min(620px,94vw);max-height:88vh;min-height:520px;
  background:var(--surface);color:var(--text);box-shadow:0 20px 60px rgba(0,0,0,.35);overflow:hidden;
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;}
#newTaskModal[open]{display:flex;flex-direction:column;}
#newTaskModal::backdrop{background:rgba(0,0,0,.52);backdrop-filter:blur(3px);}
#newTaskModal .modal-body{overflow-y:auto;}

#bulkEditModal{border:none;border-radius:12px;padding:0;width:min(480px,94vw);max-height:88vh;
  background:var(--surface);color:var(--text);box-shadow:0 20px 60px rgba(0,0,0,.35);overflow:hidden;
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;}
#bulkEditModal[open]{display:flex;flex-direction:column;}
#bulkEditModal::backdrop{background:rgba(0,0,0,.52);backdrop-filter:blur(3px);}
#bulkEditModal .modal-body{overflow-y:auto;}

.toast{position:fixed;top:16px;left:50%;transform:translateX(-50%) translateY(-12px);z-index:9999;
  padding:11px 20px;border-radius:8px;font-size:13px;font-weight:700;color:#fff;border:none;margin:0;
  box-shadow:0 8px 24px rgba(0,0,0,.25);opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0);}
.toast.ok{background:#16a34a;}
.toast.err{background:#dc2626;}
.modal-hdr{padding:14px 18px;border-bottom:1px solid var(--border);background:var(--hdr);
  display:flex;justify-content:space-between;align-items:flex-start;flex-shrink:0;gap:12px;}
.modal-hdr-info{flex:1;min-width:0;}
.modal-code{font-size:11px;font-weight:800;color:rgba(255,255,255,.75);margin-bottom:3px;}
/* Nº 68 (ajuste adicional, 2026-08-27, a peticion explicita de Javi): variante en linea de
   .modal-code para el modal de detalle de tarea -- mismo color/peso, sin el margen inferior
   que ya no hace falta al ir junto al nombre en vez de en su propia linea. Los demas modales
   que reutilizan .modal-code (Proyecto, Historial de comentarios) no se tocan. */
/* Nº 68 (4ª ronda, 2026-08-27, a peticion explicita de Javi): "El nombre deberia aparecer a
   continuacion del numero sea cual sea el tamano del nombre de la tarea" -- antes, con
   flex-wrap:wrap en .modal-title-row, si el nombre no cabia entero junto al numero en la
   anchura disponible, todo el elemento .modal-title saltaba en bloque a una segunda linea
   (flex-wrap mueve items enteros, no rompe el texto dentro de uno). Se quita flex-wrap:wrap
   del contenedor (vuelve al nowrap por defecto, asi los dos items ya no pueden repartirse en
   distintas lineas) y en su lugar .modal-title pasa a flex:1 1 auto + min-width:0 para poder
   encogerse hasta la anchura que le sobra junto al numero y que sea el TEXTO el que haga salto
   de linea dentro de su propia caja (word-wrap por defecto) -- asi el nombre siempre empieza
   pegado al numero, y si es largo continua en la siguiente linea pero ya dentro del bloque del
   nombre, no el nombre entero debajo del numero. .modal-code-inline pasa a flex-shrink:0 para
   que el numero nunca se comprima ni haga wrap. */
.modal-title-row{display:flex;align-items:baseline;gap:6px;}
/* Nº 68 (2ª ronda, 2026-08-27, a peticion explicita de Javi: "el tamano del numero debe
   ser el mismo que el del nombre"): iguala el font-size de .modal-code-inline al de
   .modal-title (15px) -- el color/peso propios de .modal-code (mas tenue, mas fino) se
   mantienen para poder distinguir numero de nombre pese al mismo tamano. */
/* Nº 68 (3ª ronda, 2026-08-27, a peticion explicita de Javi): sube 1px mas el numero (15px->16px)
   y le da color propio (ambar #fbbf24) en vez de heredar el blanco atenuado de .modal-code --
   con el mismo tamano que .modal-title el peso/opacidad ya no bastaban para diferenciarlos a
   simple vista. El fondo de .modal-hdr (--hdr) es el mismo degradado azul marino en claro y en
   oscuro (no cambia con el tema), asi que un unico color de acento funciona en ambos modos;
   contraste comprobado: ~8:1 sobre el extremo mas oscuro del degradado y ~4:1 sobre el mas claro. */
.modal-code-inline{margin-bottom:0;font-size:16px;color:#fbbf24;flex-shrink:0;}
.modal-title{font-size:15px;font-weight:700;color:#fff;flex:1 1 auto;min-width:0;overflow-wrap:break-word;}
.modal-badges{margin-top:6px;display:flex;gap:6px;flex-wrap:wrap;align-items:center;}
/* Nº 123 (2ª ronda): texto "Creada por" en linea dentro de .modal-badges, mismo estilo
   tenue que tenia el antiguo #mCreada (ver creadoPorHtml() en JS). */
.modal-created-inline{font-size:10.5px;color:rgba(255,255,255,.6);}
/* Nota "Eres colaborador/a en esta tarea" (2026-08-29, a peticion explicita de Javi): linea
   propia debajo de #mBadges (no dentro de la fila de chips), visible solo cuando CURRENT_USER
   esta en MAP_COLAB_POR_TAREA para la tarea abierta y NO es la persona asignada -- ver
   pintarBadgesModal() en JS, que la repinta en el mismo punto donde repinta el chip de
   Asignado a. display:none por defecto en el HTML para que no parpadee visible en el primer
   pintado antes de que corra el JS. */
.modal-collab-note{margin-top:4px;font-size:10.5px;font-weight:600;color:#93c5fd;}
.modal-close{border:none;background:rgba(255,255,255,.15);color:#fff;width:30px;height:30px;border-radius:6px;
  cursor:pointer;font-size:15px;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.modal-close:hover{background:rgba(255,255,255,.3);}
/* Tarea Nº 73 (ronda 5, 2026-08-28): Guardar/Guardar y cerrar de la cabecera pasan bastante
   tiempo deshabilitados (mientras no haya cambios pendientes, ver actualizarBotonesGuardarCabecera
   en JS) -- antes ningun boton .modal-close se deshabilitaba mas que un instante durante su propio
   guardado, asi que no hacia falta un estilo visual propio para ese estado. */
.modal-close:disabled{opacity:.45;cursor:not-allowed;}
.modal-body{flex:1 1 auto;min-width:0;min-height:0;overflow-y:auto;position:relative;overscroll-behavior:contain;}
/* Añadido para passwordModal (publicación web): el resto de modales de este archivo coloca sus
   botones de acción sueltos dentro de .modal-body en vez de usar un pie de modal dedicado, pero
   passwordModal replica el patrón modal-ftr de req17-web-piloto por claridad visual. */
.modal-ftr{padding:12px 18px;border-top:1px solid var(--border);display:flex;justify-content:flex-end;gap:8px;flex-shrink:0;}
/* passwordModal es el único diálogo del archivo sin regla propia de posición (el resto usa
   #idModal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);...} explícito en vez
   de fiarse del centrado nativo de <dialog>, que no siempre queda realmente centrado) — se añade
   aquí siguiendo el mismo patrón para que también se muestre centrado en la pantalla. */
#passwordModal{border:none;border-radius:12px;padding:0;width:min(420px,92vw);
  background:var(--surface);color:var(--text);box-shadow:0 20px 60px rgba(0,0,0,.35);overflow:hidden;
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;}
#passwordModal[open]{display:flex;flex-direction:column;}
#passwordModal::backdrop{background:rgba(0,0,0,.52);backdrop-filter:blur(3px);}

/* miFotoModal (autoservicio "Foto de perfil", CC-XXX): mismo patrón de posicionamiento que
   #passwordModal, por lo mismo — diálogo sin ancestro directo en #appRoot en el que apoyarse. */
#miFotoModal{border:none;border-radius:12px;padding:0;width:min(420px,92vw);
  background:var(--surface);color:var(--text);box-shadow:0 20px 60px rgba(0,0,0,.35);overflow:hidden;
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;}
#miFotoModal[open]{display:flex;flex-direction:column;}
#miFotoModal::backdrop{background:rgba(0,0,0,.52);backdrop-filter:blur(3px);}

.modal-props{padding:13px 18px;display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;border-bottom:1px solid var(--border);}
.prop-label{font-size:10px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.5px;margin-bottom:1px;}
.prop-val{font-size:12.5px;color:var(--text2);background:var(--surface2);border-radius:6px;padding:4px 7px;display:block;}

.hierarchy-section{padding:13px 18px;border-bottom:1px solid var(--border);background:var(--surface2);}
/* Vista escalonada (a petición explícita de Javi, 2026-07-31): cada nivel del árbol se indenta
   más que el anterior -- padre (0px) -> conector -> actual (20px) -> conector -> hijas (40px),
   listadas en columna, no en fila. Sin borde azul en la tarea actual (solo el fondo tintado ya
   basta para resaltarla). */
/* Tarea Nº 109 (2026-08-26, ronda 5): a petición de Javi ("mucho espacio vertical desaprovechado")
   se quitan las etiquetas "Padre"/"Hijas" y las líneas verticales conectoras (.hier-connector*,
   ya sin uso en ningún otro sitio del archivo -- confirmado por búsqueda antes de borrar); la
   indentación en cascada que ya tenían padre(0)->actual(20px)->hijas(40px) es la que transmite
   la jerarquía. gap:4px en .hier-tree sustituye a la altura de 10px de los conectores como único
   respiro entre filas. */
.hier-tree{display:flex;flex-direction:column;gap:4px;}
.hier-item{background:var(--surface2);border-radius:6px;padding:7px 10px;margin-bottom:5px;cursor:pointer;
  display:flex;gap:8px;align-items:baseline;transition:background .12s;}
.hier-item:hover{background:rgba(37,99,235,.1);}
.hier-item .hcode{font-weight:800;color:var(--primary);font-size:9px;flex-shrink:0;}
.hier-item .hname{font-size:10px;color:var(--text2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.hier-empty{font-size:9px;color:var(--text3);font-style:italic;padding:4px 0;}
.hier-current{background:rgba(37,99,235,.14);border-radius:6px;padding:7px 10px;margin-left:20px;
  display:flex;gap:8px;align-items:baseline;cursor:default;}
.hier-current .hcode{font-weight:800;color:var(--primary);font-size:9px;flex-shrink:0;}
.hier-current .hname{font-size:10.5px;color:var(--text);font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.hier-children-head{display:flex;align-items:center;justify-content:flex-end;margin-left:40px;}
.hier-children-row{display:flex;flex-direction:column;gap:5px;margin-left:40px;}
.hier-children-row .hier-item{width:100%;margin-bottom:0;}

/* ── ÁRBOL EDT (tarea Nº 71, Backlog de "Mis tareas", 2026-08-05) ───────────
   Mismo patrón visual que el árbol Cliente→Contrato→Proyecto del panel admin (.tree-* de
   admin/index.html) -- a petición explícita de Javi, para que ambos árboles se vean y se
   manejen igual. Aquí la jerarquía es de profundidad variable (Cuenta de control -> Paquete de
   trabajo -> Épica -> Funcionalidad -> Historia de usuario -> Tarea), no de niveles fijos como
   en el admin, así que solo hace falta un único juego de clases (no una por nivel). */
.tree-client{border-bottom:1px solid var(--border);padding:6px 0;}
.tree-client:last-child{border-bottom:none;}
.tree-row{display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:6px;transition:background .1s;cursor:pointer;}
.tree-row:hover{background:var(--surface2);}
.tree-row.client-row{font-weight:700;}
.tree-icon{font-size:14px;flex-shrink:0;}
.tree-name{flex:1;min-width:0;font-size:12px;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.tree-code{font-size:9px;color:var(--primary);font-weight:700;margin-left:4px;}
.tree-projects{margin-left:26px;border-left:2px solid var(--border);padding-left:4px;overflow:hidden;}
.tree-projects.collapsed{display:none;}
.tree-toggle{width:18px;height:18px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-size:11px;color:var(--text3);border-radius:4px;transition:background .12s,transform .12s;cursor:pointer;}
.tree-toggle:hover{background:var(--border);color:var(--text2);}
.tree-toggle.collapsed{transform:rotate(-90deg);}
.tree-empty{font-size:11px;color:var(--text3);font-style:italic;padding:4px 0 4px 40px;}

.related-section{padding:13px 18px;border-bottom:1px solid var(--border);z-index:5;}
.rel-badge{font-size:10px;font-weight:700;padding:2px 7px;border-radius:10px;flex-shrink:0;white-space:nowrap;}
.rel-del{color:var(--text3);font-size:16px;line-height:1;cursor:pointer;padding:0 4px;flex-shrink:0;}
.rel-del:hover{color:#dc2626;}

.hours-section{padding:11px 18px;border-bottom:1px solid var(--border);background:var(--surface2);}
.hours-two{display:grid;grid-template-columns:1fr 1fr 1fr;gap:6px;margin-bottom:7px;text-align:center;}
.hours-four{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:6px;margin-bottom:7px;text-align:center;}
.h-lbl{font-size:9px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.5px;}
.h-val{font-size:16px;font-weight:800;margin-top:2px;line-height:1;}
.bar-track{background:var(--bg);border-radius:4px;height:7px;overflow:hidden;}
.bar-fill{height:100%;border-radius:4px;transition:width .4s,background .3s;}
.hours-sub{font-size:10px;color:var(--text3);margin-top:4px;text-align:center;}

/* Fondo propio para la cabecera de pestañas del modal (a petición explícita de Javi: costaba
   localizarla visualmente dentro del modal, se confundía con el resto del contenido). OJO: el
   primer intento usaba var(--surface2), pero var(--surface2) y var(--surface) (fondo del propio
   diálogo/modal-body) son prácticamente el mismo tono de gris en el tema claro (#f8fafc vs
   #ffffff) — casi no se distinguían, así que Javi lo siguió viendo confundido con el fondo. Ahora
   se usa un lavado azul (tono de --primary) en vez de un gris, que sí se distingue con claridad
   tanto del blanco del tema claro como del azul marino del tema oscuro; además, sombra interior
   para separarlo visualmente del degradado de la cabecera de arriba. */
.tabs{display:flex;border-bottom:1px solid var(--border);flex-shrink:0;
  background:rgba(37,99,235,.09);box-shadow:inset 0 1px 3px rgba(0,0,0,.05);}
[data-theme="dark"] .tabs{background:rgba(59,130,246,.16);}
.tab{flex:1;padding:9px 3px;font-size:10.5px;font-weight:600;text-align:center;cursor:pointer;color:var(--text2);
  border-bottom:2px solid transparent;transition:color .12s,border-color .12s,background .12s;
  display:flex;align-items:center;justify-content:center;}
.tab.active{color:var(--primary);border-bottom-color:var(--primary);background:var(--surface);}
.tab:hover:not(.active){color:var(--text);}
.action-body{padding:14px 18px;}
.tab-panel{display:none;}
.tab-panel.visible{display:block;}

.form-group{margin-bottom:10px;}
.form-label{font-size:11px;font-weight:600;color:var(--text2);margin-bottom:3px;display:block;}
.form-control{width:100%;border:1px solid var(--border);border-radius:6px;padding:6px 10px;font-size:13px;
  font-family:inherit;color:var(--text);background:var(--surface);transition:border-color .15s,background .25s,color .25s;}
.form-control:focus{outline:none;border-color:var(--primary);box-shadow:0 0 0 3px rgba(37,99,235,.1);}
textarea.form-control{resize:vertical;min-height:56px;}
/* Nº 77 (ajuste adicional, 2026-08-27, a peticion explicita de Javi: "con el ajuste que
   hemos hecho en el modal, podemos aumentar el largo de la caja a 8 lineas"): la Descripcion
   de una actividad se auto-ajusta a su contenido (hasta 8 lineas COMO TOPE, antes 2) en vez
   de arrancar siempre con el min-height generico de .form-control -- por eso
   Nº 77 (2ª ronda): el atributo rows del <textarea> se deja en 1 (no en 8) porque rows fija
   un SUELO de altura para el calculo "height:auto" -> scrollHeight que hace
   medirYColapsarDescripcion() en JS; con rows=8 la caja no bajaba nunca de 8 lineas aunque
   estuviera vacia o el texto ocupara menos -- con rows=1 el suelo es minimo y el JS es quien
   decide la altura real (todo el contenido si son menos de 8 lineas, tope de 8 si son mas). */
/*
   necesita min-height:0 propio; la altura real la fija medirYColapsarDescripcion() en JS. El
   enlace "Leer más..."/"Leer menos" convive con el modo edición (a petición explícita de
   Javi): es el mismo textarea el que se expande/colapsa, no una vista de solo lectura aparte. */
#mDescripcionEdit{min-height:0;}
/* Tarea Nº 73 (ronda 4, 2026-08-28, a peticion explicita de Javi): rows vuelve a 1 (via
   ~1820, HTML) -- con rows=3 (puesto en la ronda 2 de esta misma tarea) el "suelo" de altura
   impedia que medirYColapsarDescripcion() midiera correctamente 1 sola linea cuando la
   Descripcion esta vacia, mismo problema ya documentado en su dia para la tarea 77 (2a ronda):
   con rows=N la caja no baja nunca de N lineas aunque el contenido real sea mas corto. */
.desc-toggle-row{display:flex;justify-content:space-between;align-items:center;gap:8px;margin-top:2px;}
.desc-toggle-link{display:none;font-size:11.5px;font-style:italic;color:var(--primary);cursor:pointer;user-select:none;}
.desc-toggle-link:hover{text-decoration:underline;}
/* Tarea Nº 73 (ronda 4): boton "Ampliar", SOLO visible cuando la Descripcion esta vacia (ver
   medirYColapsarDescripcion() en JS) -- pasa la caja de 1 a 5 lineas de un clic, para dar
   espacio a escribir sin tener que abrir "Leer mas..." (que no aplica a un campo vacio: no hay
   nada que "leer de mas"). Mismo estilo visual que .desc-toggle-link (enlace en cursiva), pero
   sin text-align:right propio -- la alineacion a la izquierda la da .desc-toggle-row de arriba
   (justify-content:space-between: Ampliar a la izquierda, Leer mas... a la derecha). */
.desc-ampliar-btn{display:none;font-size:11.5px;font-style:italic;color:var(--primary);cursor:pointer;user-select:none;}
.desc-ampliar-btn:hover{text-decoration:underline;}
.two-col{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin-bottom:10px;}
.hint{font-size:10px;color:var(--text3);margin-top:3px;}

/* Campos precargados al "Copiar tarea": cursiva para invitar a revisar/editar el valor, más un
   botón de check verde al lado que confirma el valor (quita la cursiva) sin tocar el propio dato. */
.nt-copy-row{display:flex;align-items:center;gap:6px;}
.nt-copy-row .form-control{flex:1;min-width:0;}
.nt-copy-row .ms-wrap{flex:1;min-width:0;}
input.nt-copied,select.nt-copied,textarea.nt-copied{font-style:italic;}
.ms-btn.nt-copied{font-style:italic;}
.nt-confirm-btn{display:none;flex-shrink:0;width:22px;height:22px;border:none;border-radius:50%;
  background:#16a34a;color:#fff;font-size:12px;font-weight:700;cursor:pointer;align-items:center;
  justify-content:center;padding:0;}
.nt-confirm-btn:hover{background:#15803d;}
.nt-confirm-btn.show{display:flex;}

/* Campos generales del modal de tarea (fechas, descripción): cada uno tiene su propio botón de
   guardado individual en vez de un único botón "Guardar" global para toda la sección. */
.field-row{display:flex;align-items:center;gap:6px;}
.field-row .form-control{flex:1;min-width:0;}
.field-save-btn{flex-shrink:0;width:22px;height:22px;border:none;border-radius:50%;
  background:#2563eb;color:#fff;font-size:12px;font-weight:700;cursor:pointer;display:flex;
  align-items:center;justify-content:center;padding:0;}
.field-save-btn:hover{background:#1d4ed8;}
.field-save-btn:disabled{opacity:.5;cursor:not-allowed;}

.btn-action{width:auto;padding:8px 18px;border:none;border-radius:6px;font-size:13px;font-weight:700;cursor:pointer;
  font-family:inherit;transition:opacity .15s,transform .1s;}
.btn-action:active{transform:scale(.98);}
.btn-action:disabled{opacity:.5;cursor:not-allowed;}
.btn-blue{background:#2563eb;color:#fff;}
.btn-green{background:#16a34a;color:#fff;}
.btn-orange{background:#ea580c;color:#fff;}
.btn-purple{background:#7c3aed;color:#fff;}

.feedback{margin-top:7px;padding:6px 11px;border-radius:6px;font-size:11px;display:inline-block;}
.fb-ok{background:#dcfce7;color:#15803d;}
.fb-err{background:#fee2e2;color:#b91c1c;}

/* Fecha límite vencida dentro del modal de tarea (a petición de Javi, 2026-08-01): la app ya
   marca "vencida" en Mis Tareas/Notas, pero el propio campo del modal no daba ninguna pista
   visual. Ver esVencida()/actualizarEstiloFechaLimite(). */
#mFechaLimite.fecha-vencida{border-color:#dc2626;background:#fee2e2;color:#b91c1c;font-weight:700;}
[data-theme="dark"] #mFechaLimite.fecha-vencida{border-color:#b91c1c;background:#3a1414;color:#fca5a5;}

.comment-tag-sys{display:inline-block;background:var(--surface2);color:var(--text3);font-size:9.5px;font-weight:700;padding:1px 7px;border-radius:8px;margin-left:5px;letter-spacing:.2px;}

.comments-section{border-top:2px solid var(--border);padding:13px 18px 18px;position:relative;background:var(--surface2);}
.comments-hdr{font-size:10px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.5px;margin-bottom:8px;}
.comment-history{max-height:min(50vh,480px);overflow-y:auto;border:1px solid var(--border);border-radius:6px;margin-top:8px;}
.comment-loading{text-align:center;padding:12px;font-size:11px;color:var(--text3);}

/* ── MENCIONES ───────────────────────── */
.mentions-overlay{position:fixed;inset:0;background:rgba(0,0,0,.35);z-index:299;display:none;}
.mentions-panel{position:fixed;top:0;right:0;width:350px;height:100vh;
  background:var(--surface);box-shadow:-4px 0 24px rgba(0,0,0,.22);
  z-index:300;display:flex;flex-direction:column;
  transform:translateX(100%);transition:transform .25s cubic-bezier(.4,0,.2,1);}
.mentions-panel.open{transform:translateX(0);}
.mentions-pnl-hdr{padding:13px 16px;border-bottom:1px solid var(--border);
  display:flex;justify-content:space-between;align-items:center;flex-shrink:0;background:var(--hdr);}
.mentions-pnl-title{font-size:14px;font-weight:700;color:#fff;}
.btn-close-pnl{border:none;background:rgba(255,255,255,.15);color:#fff;
  width:28px;height:28px;border-radius:6px;cursor:pointer;font-size:14px;
  display:flex;align-items:center;justify-content:center;}
.btn-close-pnl:hover{background:rgba(255,255,255,.3);}
.mentions-list{flex:1;overflow-y:auto;padding:10px;}
.mention-item{background:var(--surface2);border-radius:8px;padding:10px 12px;
  margin-bottom:8px;border-left:3px solid #f59e0b;}
.mention-item.leida{opacity:.5;border-left-color:var(--border);}
.mention-task{font-size:11px;font-weight:700;color:var(--primary);margin-bottom:4px;}
.mention-text{font-size:12px;color:var(--text);margin-bottom:5px;word-break:break-word;line-height:1.5;white-space:pre-line;}
.mention-meta{font-size:10px;color:var(--text3);margin-bottom:6px;}
.mention-actions{display:flex;gap:6px;}
.btn-mark-read{border:none;padding:4px 10px;border-radius:5px;font-size:11px;
  font-weight:600;cursor:pointer;background:#fef3c7;color:#92400e;transition:background .15s;}
.btn-mark-read:hover{background:#fde68a;}
.btn-mark-read:disabled{opacity:.4;cursor:not-allowed;}
.btn-view-task-sm{border:none;padding:4px 10px;border-radius:5px;font-size:11px;
  font-weight:600;cursor:pointer;background:#dbeafe;color:#1d4ed8;transition:background .15s;}
.btn-view-task-sm:hover{background:#bfdbfe;}
/* Bandeja de entrada (2026-07-28): punto azul de "sin leer" en la tarjeta + botón individual que
   alterna entre "Marcar como leído" (reutiliza .btn-mark-read) y "Archivar" (.btn-archive-sm). */
.bandeja-unread-dot{display:inline-block;width:8px;height:8px;border-radius:50%;
  background:var(--primary);margin-right:6px;vertical-align:middle;flex-shrink:0;}
.btn-archive-sm{border:none;padding:4px 10px;border-radius:5px;font-size:11px;
  font-weight:600;cursor:pointer;background:var(--surface2);color:var(--text3);transition:background .15s;}
.btn-archive-sm:hover{background:var(--border);}
/* Tarea nº 61 (2026-08-04): botón "Marcar no leído" en la tarjeta ya leída, junto a Archivar. */
.btn-mark-unread{border:none;padding:4px 10px;border-radius:5px;font-size:11px;
  font-weight:600;cursor:pointer;background:#dbeafe;color:#1d4ed8;transition:background .15s;}
.btn-mark-unread:hover{background:#bfdbfe;}
/* Tarea Nº 130 (ajuste post-prueba, ronda 2, 2026-08-28): botones redondos con icono SVG en
   bulkBarBandeja (Marcar leídas/no leídas) -- a petición explícita de Javi tras no gustarle la
   1ª versión (emoji de texto sobre fondo verde): fondo var(--surface2)/icono var(--primary)
   (mismos tokens que el resto de la app, se adaptan solos a modo oscuro), 40px de diámetro con
   icono de 22px para que se vean más grandes y claros que el resto de botones de la barra.
   Previsualizado con Javi antes de aplicar (3 variantes servidas como fichero HTML aparte);
   eligió la variante C: sobre con flap+carta interior para "Leído", sobre cerrado con la V de la
   solapa para "No leído", tooltip con solo "Leído"/"No leído" (sin "Marcar como"). */
.btn-round{width:40px;height:40px;border-radius:50%;border:none;flex:0 0 auto;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--surface2);color:var(--primary);cursor:pointer;transition:background .15s;}
.btn-round:hover{background:var(--border);}
.btn-round svg{width:22px;height:22px;display:block;}
/* Tarea Nº 130 (ajuste post-prueba, ronda 3, 2026-08-28): variante pequeña de .btn-round para
   usarla dentro de la fila compacta de cada tarjeta de la Bandeja (.tc-top, ver bandejaBtnHtml
   en taskCardHtml), donde el botón de 40px original resultaría desproporcionado -- mismo diseño
   (fondo/color/hover), solo más pequeño. */
.btn-round-sm{width:26px;height:26px;}
.btn-round-sm svg{width:15px;height:15px;}
.mentions-empty{text-align:center;padding:50px 20px;color:var(--text3);font-size:13px;}

/* Historial de Actividad (tarea Nº 87): filtro de día en la cabecera del panel + etiqueta
   Visualización/Cambio de cada fila, reutilizando el resto de clases mentions- y mention-item de
   Menciones tal cual (mismo panel lateral, sin duplicar CSS).
   BUG encontrado y corregido 2026-08-20: este comentario, en su redacción original, mencionaba
   ambos nombres de clase separados solo por una barra, sin espacio -- y esa barra, pegada al
   asterisco final de la palabra anterior, formaba sin querer la secuencia de dos caracteres que
   cierra un comentario CSS. Cerraba este comentario a mitad de frase, dejando toda la regla
   siguiente (el propio filtro de fecha) como texto suelto inválido que el navegador descartaba
   entera. Por eso el filtro de fecha nunca tuvo fondo, padding, ni disposición en fila (ni por
   tanto el centrado que pidió Javi) desde el primer commit de esta tarea -- no era un fallo del
   ajuste de centrado en sí, sino de este comentario. Verificado en un navegador de prueba aislado
   comparando el estilo definido en el código con el estilo realmente calculado por el navegador,
   antes y después de la corrección. Lección para el futuro: en cualquier comentario CSS, jamás
   escribir esos dos caracteres seguidos (ni siquiera como parte de una ruta o patrón de nombres)
   -- separar siempre con un espacio o reformular la frase. */
.hist-pnl-filtro{padding:10px 16px;border-bottom:1px solid var(--border);display:flex;
  align-items:center;justify-content:center;gap:8px;flex-shrink:0;font-size:12px;color:var(--text2);background:var(--surface2);}
.hist-pnl-filtro input[type=date]{font-size:12px;padding:3px 6px;border:1px solid var(--border);
  border-radius:5px;background:var(--surface);color:var(--text);}
.hist-item-tag{display:inline-block;border-radius:10px;padding:1px 7px;font-size:10px;
  font-weight:700;margin-left:6px;vertical-align:middle;}
.hist-item-tag.vis{background:#dbeafe;color:#1d4ed8;}
.hist-item-tag.cambio{background:#dcfce7;color:#15803d;}

.mention-chip{display:inline-block;background:#dbeafe;color:#1d4ed8;
  border-radius:12px;padding:1px 7px;font-size:11px;font-weight:700;}
.mention-chip.me{background:#fef3c7;color:#92400e;}
.mention-chip.task-chip{background:#dcfce7;color:#15803d;cursor:pointer;text-decoration:none;}
.mention-chip.task-chip:hover{background:#bbf7d0;}

.mention-dropdown{position:absolute;left:18px;background:var(--surface);
  border:1px solid var(--border);border-radius:8px;box-shadow:var(--shadow-md);
  z-index:100;min-width:170px;overflow:hidden;display:none;margin-top:2px;}
.mention-opt{padding:8px 14px;font-size:13px;cursor:pointer;color:var(--text);
  display:flex;align-items:center;gap:9px;transition:background .1s;}
.mention-opt:hover{background:var(--surface2);}
.mention-opt-av{width:24px;height:24px;border-radius:50%;background:var(--primary);
  color:#fff;font-size:10px;font-weight:700;display:flex;align-items:center;
  justify-content:center;flex-shrink:0;}

/* ── FILTRO MULTI-PROYECTO ───────────────── */
.ms-wrap{position:relative;}
.ms-btn{border:1px solid var(--border);border-radius:6px;padding:5px 9px;font-size:12px;
  background:var(--surface);color:var(--text);font-family:inherit;cursor:pointer;min-width:118px;
  text-align:left;display:flex;align-items:center;justify-content:space-between;gap:6px;}
.ms-btn::after{content:'\25BE';font-size:9px;color:var(--text3);margin-left:4px;}
.ms-btn:focus{outline:none;border-color:var(--primary);box-shadow:0 0 0 3px rgba(37,99,235,.12);}
.ms-menu{display:none;position:absolute;top:calc(100% + 4px);left:0;z-index:50;
  background:var(--surface);border:1px solid var(--border);border-radius:8px;
  box-shadow:var(--shadow-md);padding:6px;min-width:190px;}
.ms-menu.open{display:block;}
.ms-item{display:flex;align-items:center;gap:7px;font-size:12px;padding:5px 7px;
  border-radius:5px;cursor:pointer;color:var(--text);}
.ms-item:hover{background:var(--surface2);}
.ms-item input{width:14px;height:14px;cursor:pointer;flex-shrink:0;}
.ms-item.ms-item-hidden{display:none;}
/* Resaltado de la subcadena buscada dentro de un ms-item (tarea Nº 69, ajuste 2026-08-28 a
   petición explícita de Javi: el filtrado por subcadena ya funcionaba, pero no se veía marcada
   la coincidencia) -- ver filterMsItems(). Color fijo (no ligado a var(--primary)/tema) para que
   se lea igual que un resaltado de búsqueda normal en cualquier tema. */
.ms-hl{background:#fde047;color:#713f12;border-radius:2px;padding:0 1px;}
/* Buscador por tecleo dentro del ms-menu (tarea Nº 69): filtra los .ms-item por subcadena sin
   tocar la seleccion multiple existente (checkboxes). Vive dentro del propio menu desplegable,
   asi que "abrir el desplegable filtrado" = el menu ya esta abierto (toggleMs*) y el buscador
   filtra en vivo sobre esa lista abierta. */
.ms-search{width:100%;box-sizing:border-box;border:1px solid var(--border);border-radius:6px;
  padding:5px 7px;font-size:12px;margin-bottom:6px;font-family:inherit;}
.ms-search:focus{outline:none;border-color:var(--primary);box-shadow:0 0 0 3px rgba(37,99,235,.12);}
.ms-actions{display:flex;gap:6px;border-top:1px solid var(--border);margin-top:5px;padding-top:6px;}
/* "Combo con búsqueda" de valor único (tarea Nº 69, pestaña Backlog de Mis Tareas): mismo aspecto
   ms-btn/ms-menu/ms-item que los filtros multi-selección, pero cada .sesel-item es una opción
   única de un <select> nativo que queda oculto y sigue siendo la fuente de verdad (valor,
   opciones, onchange). max-height + overflow porque estas listas pueden ser largas (todos los
   proyectos, por ejemplo). */
.sesel-menu{max-height:260px;overflow-y:auto;}
.ms-item.sesel-item-sel{background:var(--surface2);font-weight:600;}
/* El .ms-btn genérico se dimensiona por su propio contenido (min-width:118px) -- correcto para
   la barra de filtros de "Mis Proyectos"/Backlog, donde varios combos van uno junto a otro y así
   se queda igual que antes. Pero en los modales "Nueva tarea"/"Copiar" (.nt-copy-row, ya con
   flex:1 sobre el wrap) y "Edición masiva" (#bulkEditModal, .form-group es un bloque normal que
   ya ocupa el 100% del ancho) el combo "sesel" sustituye a un <select class="form-control"> que
   sí llenaba todo el campo -- sin esto el botón queda visualmente más corto que el resto de
   campos del formulario, rompiendo la alineación (aviso de Javi, Nº 69). Selectores específicos a
   esos dos sitios para no tocar el ancho (intencionadamente por contenido) de los combos de la
   barra de filtros de Mis Proyectos/Backlog. */
.nt-copy-row .ms-wrap .ms-btn,
#bulkEditModal .ms-wrap .ms-btn{width:100%;box-sizing:border-box;}
.ms-actions button{border:none;background:transparent;color:var(--primary);font-size:11px;
  font-weight:600;cursor:pointer;text-decoration:underline;padding:2px;}

/* ── TABS (nivel página) ─────────────────── */
.tabbar{background:var(--surface);border-bottom:1px solid var(--border);
  display:flex;padding:0 20px;}
.tabbtn{padding:12px 18px;font-size:13px;font-weight:700;color:var(--text3);
  cursor:pointer;border-bottom:3px solid transparent;transition:color .12s,border-color .12s;}
.tabbtn.active{color:var(--primary);border-bottom-color:var(--primary);}
.tabbtn:hover:not(.active){color:var(--text2);}
/* Botón "Manual" (a petición explícita de Javi, 2026-07-27): abre en pestaña nueva el PDF del
   manual de usuario correspondiente al rol activo. margin-left:auto lo empuja al extremo derecho
   de .tabbar (que ya es display:flex), sin tocar el resto de pestañas. */
.tabbtn-help{margin-left:auto;padding:12px 18px;font-size:13px;font-weight:700;color:var(--text3);
  text-decoration:none;display:flex;align-items:center;gap:5px;white-space:nowrap;}
.tabbtn-help:hover{color:var(--primary);}
.tabpanel{display:none;}
.tabpanel.visible{display:block;}

/* ── TIME-LINE VACACIONES EQUIPO (calendario tipo Gantt, portado de REQ-8/REQ-17) ── */
.tl-toolbar{display:flex;align-items:center;gap:8px;}
.tl-month-label{font-size:13px;font-weight:700;color:var(--text);min-width:170px;text-align:center;text-transform:capitalize;}
.tl-zoom-label{font-size:11px;font-weight:700;color:var(--text2);min-width:64px;text-align:center;}
.tl-table{display:grid;grid-template-columns:220px repeat(3,48px) 1fr;font-size:12px;}
/* CC pendiente (2026-08-23): el Cronograma de proyectos NO usa .tl-table (esa rejilla de 5
   columnas está pensada para Vacaciones del equipo: etiqueta + 3 resumen Plan/Disf/Pend + pista).
   renderCronograma() solo genera 2 celdas por fila (etiqueta + pista), así que compartir esa
   clase hacía que el grid auto-flow desplazara cada fila 3 columnas de más, produciendo barras y
   textos solapados/cortados. Rejilla propia de 2 columnas para no volver a mezclar ambas vistas. */
.tl-table-2col{display:grid;grid-template-columns:220px 1fr;font-size:12px;}
.tl-summary-header{border-bottom:1px solid var(--border);font-size:9px;text-align:center;color:var(--text3);
  padding:4px 2px;font-weight:700;}
.tl-summary-cell{border-bottom:1px solid var(--border);text-align:center;font-size:12px;font-weight:600;
  color:var(--text);display:flex;align-items:center;justify-content:center;}
/* Colores por columna (tarea Nº 91, a petición de Javi): Planificados azul, Disfrutados
   naranja, Pendientes verde -- mismo criterio que admin/index.html. */
.tl-summary-header.tl-sum-plan,.tl-summary-cell.tl-sum-plan{color:#2563eb;}
.tl-summary-header.tl-sum-disf,.tl-summary-cell.tl-sum-disf{color:#ea580c;}
.tl-summary-header.tl-sum-pend,.tl-summary-cell.tl-sum-pend{color:#16a34a;}
.tl-corner{border-bottom:1px solid var(--border);}
.tl-daysheader{display:grid;border-bottom:1px solid var(--border);}
.tl-day{font-size:9px;text-align:center;color:var(--text3);padding:4px 0;border-right:1px solid var(--border);}
.tl-day.today{background:rgba(37,99,235,.10);font-weight:700;color:var(--primary);}
.tl-rowlabel{padding:8px 10px;border-bottom:1px solid var(--border);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;display:flex;flex-direction:column;justify-content:center;gap:1px;}
.tl-rowlabel .tl-pname{font-weight:700;font-size:12px;color:var(--text);overflow:hidden;text-overflow:ellipsis;}
.tl-rowlabel .tl-cname{font-size:10px;color:var(--text3);overflow:hidden;text-overflow:ellipsis;}
.tl-track{position:relative;border-bottom:1px solid var(--border);height:38px;}
.tl-track-grid{position:absolute;inset:0;display:grid;}
.tl-track-grid>div{border-right:1px solid var(--border);}
/* Sombreado de fines de semana/festivos en el zoom de día del Time-Line de Vacaciones del
   equipo (tarea Nº 89), mismo criterio que admin/index.html. */
.tl-track-grid>div.tl-weekend{background:rgba(148,163,184,.20);}
.tl-track-grid>div.tl-festivo-nacional{background:rgba(220,38,38,.12);}
.tl-track-grid>div.tl-festivo-local{background:rgba(37,99,235,.12);}
.tl-bar{position:absolute;top:7px;height:24px;border-radius:5px;display:flex;align-items:center;
  padding:0 8px;font-size:10.5px;font-weight:700;color:#fff;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;cursor:default;box-shadow:var(--shadow);min-width:6px;background:#94a3b8;}
/* Leyenda de colores del Cronograma (Tarea Nº 55), mismo patrón .tl-legend* que el Timeline de
   Vacaciones del equipo en admin/index.html (portado tal cual, no existía en index.html). */
.tl-legend{display:flex;gap:14px;flex-wrap:wrap;padding:0 0 10px 220px;font-size:11px;color:var(--text2);}
.tl-legend-item{display:flex;align-items:center;gap:5px;}
.tl-legend-dot{width:10px;height:10px;border-radius:3px;flex-shrink:0;}
/* Leyenda del sombreado de fin de semana/festivo (tarea Nº 89), debajo de la rejilla en vez de
   encima: mismo bloque .tl-legend* de siempre, solo cambia el padding (arriba, no abajo). */
.tl-legend-festivos{padding:10px 0 0 220px;}
.vac-toolbar{display:flex;gap:10px;align-items:center;padding:14px 20px;flex-wrap:wrap;}
.btn-ghost{background:var(--surface2);color:var(--text2);}
.btn-sm{width:auto;padding:6px 12px;font-size:12px;}
.card{background:var(--surface);border-radius:10px;padding:13px 15px;box-shadow:var(--shadow);}

/* ── DRAG & DROP de filas (reordenar Prioridad) ── */
.drag-handle-cell{width:22px;text-align:center;color:var(--text3);cursor:grab;
  font-size:12px;letter-spacing:-2px;user-select:none;}
.drag-handle-cell:active{cursor:grabbing;}
tr.row-dragging{opacity:.4;}
tr.row-drop-above td{border-top:3px solid var(--primary);}
tr.row-drop-below td{border-bottom:3px solid var(--primary);}

/* ── VISTA DE TABLERO (Kanban) — Mis Proyectos, a petición de Javi (2026-07-23) ── */
.view-toggle{display:flex;gap:4px;background:var(--surface2);border-radius:8px;padding:3px;flex-shrink:0;}
.view-toggle-btn{border:none;background:transparent;color:var(--text2);padding:5px 12px;border-radius:6px;
  font-size:12px;font-weight:700;cursor:pointer;font-family:inherit;transition:background .15s,color .15s;}
.view-toggle-btn.active{background:var(--surface);color:var(--primary);box-shadow:var(--shadow);}
.edt-niveles{display:flex;align-items:center;gap:6px;margin-bottom:8px;font-size:11px;}
.edt-niveles-label{color:var(--text3);margin-right:2px;}
.edt-nivel-btn{border:1px solid var(--border);background:var(--surface);color:var(--text2);padding:3px 9px;border-radius:6px;font-size:11px;font-weight:700;cursor:pointer;font-family:inherit;transition:background .15s,color .15s;}
.edt-nivel-btn:hover{background:var(--surface2);color:var(--primary);}
.kanban-board{display:flex;gap:12px;overflow-x:auto;padding-bottom:10px;align-items:flex-start;}
.kanban-col{flex:0 0 260px;width:260px;background:var(--surface2);border-radius:10px;overflow:hidden;
  display:flex;flex-direction:column;max-height:calc(100vh - 320px);}
.kanban-col-hdr{padding:9px 12px;font-size:12px;font-weight:800;letter-spacing:.2px;
  display:flex;align-items:center;justify-content:space-between;flex-shrink:0;}
.kanban-col-count{font-size:11px;font-weight:700;opacity:.75;}
.kanban-col-body{padding:8px;overflow-y:auto;flex:1 1 auto;min-height:40px;}
.kanban-card{background:var(--surface);border-radius:8px;padding:9px 10px;margin-bottom:8px;
  box-shadow:var(--shadow);cursor:grab;transition:opacity .15s;}
.kanban-card:active{cursor:grabbing;}
.kanban-card:last-child{margin-bottom:0;}
.kanban-card-name{font-size:12.5px;line-height:15px;min-height:30px;font-weight:600;color:var(--text);margin-bottom:6px;
  overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;}
.kanban-card-meta{display:flex;align-items:center;flex-wrap:wrap;gap:6px;font-size:10.5px;}
.kanban-card-proj{margin-top:6px;font-size:10.5px;}
.kanban-desviada{background:#fee2e2;color:#b91c1c;border-radius:8px;padding:1px 7px;font-weight:700;}
.kanban-card-dragging{opacity:.35;}
.kanban-card.kanban-drop-above{border-top:3px solid var(--primary);}
.kanban-card.kanban-drop-below{border-bottom:3px solid var(--primary);}

/* ══════════════════════════════════════════════════════════════════
   MÓVIL (tarea Nº 20, aproximación solo-CSS, 2026-08-07): breakpoint
   único de 640px, igual que la propuesta de mockup. No toca tablet
   (1024px) ni escritorio -- solo se activa por debajo de 640px. No
   convierte tablas/Gantt en tarjetas/lista (eso queda para una fase
   posterior con cambios de JS); aquí solo se corrige lo que hoy no
   tiene ningún manejo de overflow y se saldría o aplastaría en una
   pantalla estrecha. Tablas (.table-wrap) y Gantt de Cronograma
   (#cronoScrollWrap) ya scrollean horizontalmente hoy -- no se tocan. */
/* Tarea Nº 73 (ronda 5, 2026-08-28, a peticion explicita de Javi): en escritorio (>640px, mismo
   punto de corte que el resto de la app) se ocultan los botones de check azul de la pestaña
   Detalles (.field-save-btn: Estado, Nombre, Fecha inicio/fin/limite, Descripcion) -- el guardado
   pasa a hacerse solo con "Guardar"/"Guardar y cerrar" de la cabecera. En movil se mantienen
   visibles y funcionales sin cambios (a peticion explicita: "en la version escritorio vamos a
   ocultar los botones de check azul"). .field-save-btn no se usa fuera de #taskModal.
   Tarea Nº 73 (ronda 6, 2026-08-28, a peticion explicita de Javi -- "vamos a ocultar los botones
   de guardar de las acciones, dedicaciones y comentarios"): mismo criterio, extendido a los
   botones de guardado individuales de esas 3 pestañas -- Actualizar planificación, Confirmar
   reasignación, Guardar colaboradores y Guardar actividad (Jerarquía) en Acciones; Registrar
   dedicación en Dedicaciones; Publicar comentario en Comentarios. Son .btn-action (no
   .field-save-btn, un componente visual distinto), asi que se ocultan por id -- todos unicos en
   el documento -- en vez de por clase, para no afectar sin querer a otros .btn-action de este
   mismo modal (p.ej. "Ver todas" en Dedicaciones, que no guarda nada y sigue haciendo falta) ni
   de otros modales que tambien usan .btn-action (Nueva actividad, Edición masiva...). Todos ellos
   ya estaban cubiertos por camposConCambiosPendientes()/guardarTodoPendiente() desde antes de
   esta tarea (Planificación, Reasignación, Colaboradores, Tipo de actividad, Dedicación sin
   registrar, Comentario sin publicar son candidatos ahi), asi que Guardar/Guardar y cerrar de la
   cabecera ya guardaban esto tambien -- ocultar sus botones propios no quita ninguna funcion, solo
   centraliza el punto de guardado en escritorio. En movil se mantienen visibles y funcionales. */
@media (min-width:641px){
  #taskModal .field-save-btn,
  #btnActualizarPlan,
  #btnReasignarSimple,
  #btnGuardarColaboradores,
  #btnActualizarJerarquia,
  #btnGuardarDedicacion,
  #btnPublicarComentario,
  #btnGuardarEnfoque{display:none;}
}
@media (max-width:640px){
  .header{flex-wrap:wrap;row-gap:8px;}
  .hdr-left,.hdr-right{flex-wrap:wrap;row-gap:6px;width:100%;}
  .hdr-right{justify-content:flex-start;}
  .tabbar{overflow-x:auto;-webkit-overflow-scrolling:touch;}
  .tabbtn{white-space:nowrap;}
  .tl-header{flex-wrap:wrap;row-gap:8px;}
  .view-toggle{overflow-x:auto;max-width:100%;-webkit-overflow-scrolling:touch;}
  .summary-row,#summaryRowMT{grid-template-columns:repeat(auto-fit,minmax(100px,1fr));}
  .mt-top-row{flex-direction:column;}
  .pie-card{flex:1 1 auto;}
  .mentions-panel{width:100%;}
  .modal-body{overflow-x:hidden;}
  .modal-props{grid-template-columns:minmax(0,1fr) minmax(0,1fr);}
  .modal-props>div[style*="repeat(3,1fr)"]{grid-template-columns:1fr !important;}
  .two-col{grid-template-columns:minmax(0,1fr);}
  .hours-four{grid-template-columns:repeat(2,minmax(0,1fr));}
  .kanban-col{width:85vw;flex:0 0 85vw;}
  .nota-item{flex-wrap:wrap;}
  .nota-texto{min-width:160px;}
  .tc-top{flex-wrap:wrap;row-gap:6px;}
  .task-info{flex:1 1 220px;min-width:220px;}
  .filters,.search-bar{padding-left:12px;padding-right:12px;}
  .content{padding-left:12px;padding-right:12px;}
  .form-control,.btn-action{min-height:44px;}
}

/* ══ Tarea Nº 73 (2026-08-28): #taskModal pasa a 3 pestañas de nivel superior (Detalles/
   Acciones/Comentarios) que ocupan el ancho completo del modal en vez de repartirse en 2
   columnas fijas (tm-info-col 1fr / tm-side-col 300px, tarea 109) -- ver #tmMainTabsBar/
   switchMainTab() en JS. Se reutilizan las clases .tabs/.tab/.tab-panel ya existentes (las
   mismas que usaban las sub-pestañas de Acciones, ahora retiradas: sus 5 secciones pasan a
   mostrarse siempre visibles, apiladas, dentro de la pestaña Acciones -- ver .action-section
   más abajo). Se aplica igual en todos los anchos de pantalla (antes el layout de 2 columnas
   solo regía desde 641px) -- por eso desaparece el @media (min-width:641px) que había aquí,
   junto con .tm-info-col/.tm-side-col/.tm-tabs-pane, que ya no existen en el DOM. */
.action-section{padding-bottom:14px;margin-bottom:14px;border-bottom:1px solid var(--border);}
.action-section:last-child{border-bottom:none;margin-bottom:0;padding-bottom:0;}
#taskModal #tmpanel-comentarios{border-top:none;}
/* Nº 73 (ronda 3, 2026-08-28, a peticion explicita de Javi): en movil la cabecera del modal se
   veia apretada y crecia mucho en vertical (numero+nombre+etiquetas compitiendo con los 3
   botones en la misma fila). .modal-hdr pasa de fila a columna SOLO dentro de #taskModal (el
   resto de modales que reutilizan .modal-hdr no se tocan), y se aplica igual en todos los
   anchos de pantalla (a peticion explicita de Javi: "aplicar en todos los tamanos"), no solo
   en movil, para mantener un unico layout -- sigue vigente en la ronda 4 (abajo), solo cambia
   QUE va dentro de cada una de las 2 filas resultantes, no el hecho de que sean 2 filas. */
#taskModal .modal-hdr{flex-direction:column;align-items:stretch;}
/* Nº 73 (ronda 4, 2026-08-28, a peticion explicita de Javi): dentro de #taskModal, cada una de
   las 2 filas de la cabecera reparte su contenido a los extremos (numero+nombre <-> boton
   cerrar; etiquetas/"Creado por" <-> botones Guardar/Copiar) via display:flex inline en el
   propio HTML -- ver #taskModal .modal-hdr en el DOM. #mBadges pierde aqui su margin-top de
   6px (pensado para cuando iba apilado DEBAJO de la fila del nombre en la misma columna, antes
   de la ronda 4): ahora es el primer elemento de su propia fila, y el espacio respecto a la
   fila anterior ya lo da el gap:12px de #taskModal .modal-hdr. El resto de usos de
   .modal-badges (fuera de #taskModal) no se tocan. */
#taskModal .modal-badges{margin-top:0;}
/* Nº 73 (ronda 3): el nombre de la tarea se trunca a UNA sola linea con "…" si no cabe, en vez
   de partirse en varias lineas (comportamiento de .modal-title por defecto, overflow-wrap:
   break-word, que se mantiene para el resto de modales). Solo dentro de #taskModal; .modal-code
   -inline ya es flex-shrink:0 y .modal-title ya es flex:1 1 auto + min-width:0 (Nº 68, 4ª
   ronda), condicion necesaria para que overflow/text-overflow funcionen en un item flex. */
#taskModal .modal-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
/* Tarea 489 (Fase A): clase de utilidad para ocultar elementos que antes llevaban
   style="display:none" inline en el HTML (retirado para poder endurecer la CSP quitando
   unsafe-inline de style-src). Declarada aqui, al FINAL de la hoja de estilos, a proposito:
   asi gana cualquier empate de cascada frente a otra clase del mismo elemento que tambien
   fije "display" (misma especificidad, un solo selector de clase cada una) -- si estuviera
   al principio, esa otra clase podria ganar por orden de aparicion y el elemento se quedaria
   visible por error. El codigo JS que necesita mostrar un elemento migrado sigue usando
   el.style.display = 'valor-explicito' (nunca vaciarlo con ''): un estilo inline con valor
   explicito SIEMPRE gana a una clase, sea cual sea el orden -- ver regla operativa n.21 / LA-009. */
.d-none{display:none}

/* Tarea 489/497 (Fase A, 2026-09-12): utilidades generadas para el resto de estilos
   inline (style="") migrados a clase, para poder retirar unsafe-inline de style-src.
   Declaradas al FINAL de la hoja de estilos (regla operativa 21: ganan los empates de
   especificidad frente a clases anteriores sobre el mismo elemento). */
.u497-00241ab{font-size:12.5px;resize:vertical}
.u497-01f6496{color:var(--primary);font-weight:600}
.u497-020d693{margin:-6px 0 10px}
.u497-03dfc26{color:var(--text3)}
.u497-042c99f{display:flex;flex-direction:column;gap:2px;min-width:0}
.u497-0466783{width:100%}
.u497-0486f78{align-items:flex-start}
.u497-06307df{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.u497-068a8dd{grid-column:1/-1}
.u497-0762f1f{display:flex;gap:8px;flex-shrink:0}
.u497-096fb4e{max-height:180px;overflow-y:auto;border:1px solid var(--border);border-radius:8px;padding:8px}
.u497-097da83{width:16px;height:16px;cursor:pointer}
.u497-0c5042b{grid-column:1/-1;display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:-4px}
.u497-0daa4ae{text-align:left;padding:5px 8px;color:var(--text3);font-weight:700;border-bottom:1px solid var(--border)}
.u497-1169661{margin:0}
.u497-1171827{color:#dc2626;padding:20px;text-align:center}
.u497-1542957{margin:4px 0 14px;width:100%}
.u497-1549ef4{padding:4px 6px;border-bottom:1px solid var(--border);text-align:right;font-weight:700}
.u497-167c59b{color:#dc2626;font-weight:800}
.u497-177865b{white-space:pre-wrap;font-size:13px;color:var(--text2)}
.u497-17b2f9e{width:auto;padding:3px 9px;font-size:10px;background:var(--surface2);color:var(--text2)}
.u497-1e29e68{margin-top:8px;padding-top:8px;border-top:1px solid var(--border);font-size:10.5px;line-height:1.6;color:var(--text2)}
.u497-1f95e0e{display:inline-block;margin-left:6px;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:700;vertical-align:middle;letter-spacing:.3px;}
.u497-1fadc7d{display:flex;justify-content:space-between;align-items:flex-start;gap:8px}
.u497-2056554{color:#dc2626}
.u497-222f128{font-size:13.5px;color:#475569;line-height:1.65}
.u497-230e016{display:flex;justify-content:space-between;gap:8px;padding:4px 0;border-bottom:1px solid var(--border)}
.u497-23270ab{font-size:11px;color:var(--text3);margin-top:2px}
.u497-23c8c70{padding:4px 6px;border-bottom:1px solid var(--border);text-align:center}
.u497-2410f0a{width:100%;height:100%;object-fit:cover;border-radius:50%}
.u497-2796555{margin:2px 0 4px}
.u497-2817fc3{font-size:40px;margin-bottom:10px}
.u497-28768b8{width:auto;padding:7px 14px;font-size:12px}
.u497-2acaf3b{width:200px}
.u497-2c576c0{width:auto;padding:0 10px;font-size:11px;gap:4px}
.u497-2d7d272{justify-content:space-between;align-items:center}
.u497-2dbb23c{background:#93c5fd}
.u497-2e00326{margin-bottom:5px}
.u497-2e73ba5{padding:4px 10px;font-size:12px}
.u497-2e75848{margin-bottom:8px;display:flex;align-items:center;justify-content:space-between;gap:8px}
.u497-2f3a4f8{padding:7px 14px;font-size:12px}
.u497-3166f0e{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;flex-wrap:wrap;gap:10px}
.u497-322e3f5{width:30px}
.u497-3329273{font-size:10px;color:var(--primary);text-decoration:underline}
.u497-3352fa4{display:flex;justify-content:space-between;align-items:flex-start;gap:8px;flex-wrap:wrap}
.u497-379d3e1{color:#16a34a;font-weight:800}
.u497-3818348{font-weight:800;color:var(--primary)}
.u497-3b09b46{background:#f1f5f9;color:#94a3b8}
.u497-3b6a3a6{cursor:pointer}
.u497-3cb0ceb{overflow-x:auto;margin:0 20px 20px}
.u497-3d23ddb{margin-top:5px;height:38px}
.u497-3de040e{width:auto;padding:4px 10px;font-size:10.5px;background:var(--surface2);color:var(--text2)}
.u497-42b71ed{flex-shrink:0;margin-left:8px;display:flex;gap:6px}
.u497-4450dc5{margin:0 20px}
.u497-44fff1c{padding:5px 12px}
.u497-469cd45{background:#cbd5e1}
.u497-494bf9c{color:#2563eb}
.u497-4ba0d33{display:none;margin:0 0 12px;font-size:13px;color:var(--muted)}
.u497-4bcf1be{flex:1;min-width:180px;padding:6px 10px;border:1px solid var(--border);border-radius:6px;background:var(--surface);color:var(--text);font-size:13px}
.u497-4e420af{margin-bottom:6px}
.u497-5328b8c{margin-top:14px;padding-top:10px;border-top:1px solid var(--border)}
.u497-579954b{width:100%;border-collapse:collapse;font-size:11.5px}
.u497-585e59a{cursor:default;justify-content:space-between;align-items:center}
.u497-58982a6{width:auto;padding:3px 9px;font-size:10px}
.u497-5d6f984{color:var(--text);font-size:15px}
.u497-5ea5a29{padding:5px 8px;border-bottom:1px solid var(--border);text-align:right;font-weight:700}
.u497-6280854{max-width:440px;background:#fff;border-radius:14px;box-shadow:0 8px 30px rgba(0,0,0,.12);padding:34px 30px;text-align:center}
.u497-62838f5{margin-top:7px}
.u497-6750b23{font-size:12.5px}
.u497-67d840f{background:rgba(255,255,255,.94);color:#1e3a5f;font-weight:700}
.u497-687895e{color:#dc2626;font-weight:600}
.u497-6a43470{margin:0;flex:1}
.u497-6a6a237{color:#f59e0b}
.u497-6b96a7d{max-height:150px;overflow-y:auto}
.u497-6bd5fb5{font-size:10.5px;color:var(--primary);background:none;border:none;cursor:pointer;text-decoration:underline;padding:0;font-family:inherit}
.u497-6c7ef67{background:#eef2ff;color:#4338ca}
.u497-6cb285c{font-size:12px}
.u497-6d00061{margin-left:auto}
.u497-6f0165c{color:#d97706;font-weight:700}
.u497-70ca298{min-width:900px}
.u497-716042e{display:flex;gap:8px;align-items:baseline;overflow:hidden;flex:1;min-width:0}
.u497-7238926{color:#16a34a}
.u497-73a8a23{margin:-2px 0 8px}
.u497-761d3ad{margin-bottom:10px}
.u497-7664778{width:auto;padding:5px 12px;font-size:11.5px;background:var(--surface2);color:var(--text2)}
.u497-769fed3{padding:20px}
.u497-78bf160{background:#16a34a}
.u497-7c2b227{font-size:11px;color:var(--text3);margin-top:1px}
.u497-7ca97b7{width:auto;font-size:11.5px;padding:5px 6px;flex-shrink:0}
.u497-7f4dca5{display:flex;align-items:center;gap:8px;cursor:pointer;margin:0}
.u497-80ba94d{text-align:center;padding:4px 6px;color:var(--text3);font-weight:700;border-bottom:1px solid var(--border)}
.u497-8487760{color:var(--text3);margin-bottom:2px}
.u497-851d787{background:var(--surface2)}
.u497-855cbf1{font-size:11px;margin-top:3px;resize:vertical}
.u497-85c7183{font-weight:600;margin-bottom:6px}
.u497-86f0672{font-size:12px;padding:5px 8px}
.u497-8748c00{text-align:right;padding:5px 8px;color:var(--text3);font-weight:700;border-bottom:1px solid var(--border)}
.u497-89d0d86{text-align:right;padding:4px 6px;color:var(--text3);font-weight:700;border-bottom:1px solid var(--border)}
.u497-8ba347e{display:flex;justify-content:space-between;align-items:center;font-size:10px;color:var(--text3);margin-top:2px}
.u497-8e11ed6{padding:18px}
.u497-8e1eb9a{min-height:100vh;display:flex;align-items:center;justify-content:center;background:#f0f4f8;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;padding:20px}
.u497-8e47af7{padding:4px 6px;border-bottom:1px solid var(--border)}
.u497-90131cf{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px;gap:8px}
.u497-9174291{margin-bottom:10px;padding:12px 14px}
.u497-936f0ac{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text2);margin-top:8px;cursor:pointer}
.u497-93a339c{display:flex;align-items:center;justify-content:space-between;font-size:11.5px;color:var(--text2);font-weight:600;margin-bottom:6px}
.u497-9494cd7{padding:5px 12px;font-size:12px;width:auto;background:var(--surface2);color:var(--text)}
.u497-94a8d45{display:flex;justify-content:space-between;align-items:center;margin:0 20px 6px;gap:10px;flex-wrap:wrap}
.u497-94b4867{text-align:left;padding:4px 6px;color:var(--text3);font-weight:700;border-bottom:1px solid var(--border)}
.u497-96ad609{margin-top:4px}
.u497-9714b43{display:none;margin-top:8px}
.u497-97ca7c1{font-size:18px;font-weight:800;color:#1a2332;margin-bottom:10px}
.u497-984a7e2{padding:5px 12px;font-size:12px;width:auto}
.u497-9a70a43{font-size:30px;margin-bottom:8px;}
.u497-9cbd067{font-size:12px;padding:4px 8px}
.u497-9d0af0f{resize:vertical}
.u497-a08bce1{margin-right:6px;vertical-align:middle;flex-shrink:0;font-size:12px}
.u497-a2a61f8{width:100%;border-collapse:collapse;font-size:11px}
.u497-a3087c0{width:150px;max-width:100%;padding:7px 12px;font-size:13px}
.u497-a393320{line-height:1;vertical-align:middle}
.u497-a478236{text-align:center;padding:5px 8px;color:var(--text3);font-weight:700;border-bottom:1px solid var(--border)}
.u497-a4f6463{display:flex;gap:8px;align-items:baseline;flex:1;min-width:0;cursor:pointer;overflow:hidden}
.u497-a548ea7{white-space:pre-wrap}
.u497-a61baee{display:flex;align-items:center;gap:6px;margin-top:6px;font-size:12px;cursor:pointer;font-weight:400}
.u497-af079da{width:38px;padding:1px 4px;font-size:11px;border:1px solid var(--border);border-radius:4px}
.u497-af7ee11{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text3)}
.u497-b460f73{width:0%;background:#16a34a}
.u497-b5c75a3{background:#16a34a;color:#fff}
.u497-b5d70de{width:auto;padding:3px 8px;font-size:10.5px;text-transform:none;letter-spacing:normal}
.u497-b756e24{margin-top:14px;padding-top:12px;border-top:1px solid var(--border)}
.u497-b924be0{width:46px;padding:2px 4px;font-size:11px;border:1px solid var(--border);border-radius:4px}
.u497-bb082fd{width:280px}
.u497-bb1d98a{padding:16px 18px}
.u497-bbc0560{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.u497-bd3b87a{max-height:150px;overflow-y:auto;border:1px solid var(--border);border-radius:8px;padding:8px}
.u497-c00d391{margin-top:3px}
.u497-c116746{margin:-4px 0 10px;line-height:1.5}
.u497-c1c85dd{padding:5px 8px;border-bottom:1px solid var(--border)}
.u497-c2e927d{color:#d97706;font-weight:600}
.u497-c2eaba9{padding:12px 10px;text-align:center;color:var(--text3);font-size:11px}
.u497-c838a30{position:relative;margin-top:6px;display:flex;gap:6px;align-items:center}
.u497-c852776{color:var(--text);white-space:pre-line}
.u497-ccca5d6{padding:4px 6px;border-bottom:1px solid var(--border);color:var(--text2);white-space:nowrap}
.u497-cd230a4{background:#fca5a5}
.u497-cefbfed{width:22px}
.u497-d03f932{resize:none;font-size:12px}
.u497-d151fc1{text-transform:none;letter-spacing:normal}
.u497-d26bd1e{color:var(--primary);text-decoration:underline;word-break:break-all}
.u497-d36044f{display:none;position:fixed;inset:0;z-index:10000;background:rgba(15,23,42,.55);align-items:center;justify-content:center;}
.u497-d461c96{position:relative}
.u497-d6a9b82{padding:5px 8px;border-bottom:1px solid var(--border);text-align:center}
.u497-da12f28{margin-bottom:12px}
.u497-dbf9c49{width:14px;height:14px;cursor:pointer}
.u497-dc2e428{color:var(--primary)}
.u497-dcdbe5f{font-size:13px;color:var(--text2);margin-bottom:18px;}
.u497-dd6a698{font-weight:700;font-size:15px;margin-bottom:6px;}
.u497-de0db80{width:64px;height:64px;font-size:20px;overflow:hidden}
.u497-dee0bfd{background:var(--surface);color:var(--text);border-radius:12px;box-shadow:0 20px 60px rgba(0,0,0,.35);padding:26px 28px;max-width:340px;text-align:center;}
.u497-df01394{display:none;background:var(--bg2,#f8fafc);border-radius:8px;padding:10px 12px}
.u497-df81a9c{color:var(--text3);margin-left:auto;white-space:nowrap}
.u497-e24f4c3{color:#d97706;cursor:pointer}
.u497-e58aa51{display:flex;justify-content:space-between;align-items:center;margin-top:12px;gap:10px}
.u497-e711c1e{height:300px}
.u497-e775556{visibility:hidden}
.u497-e82fd3c{font-size:10.5px;color:var(--primary);text-decoration:underline}
.u497-e88f9b5{padding:5px 8px;border-bottom:1px solid var(--border);color:var(--text2)}
.u497-ef0b7a1{margin-bottom:0}
.u497-f045bbe{color:var(--text)}
.u497-f1caf5a{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text3);cursor:pointer}
.u497-f20df06{display:flex;align-items:center;gap:14px;margin-bottom:4px}
.u497-f4e8fee{margin-top:12px;line-height:1.7}
.u497-f6c797b{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.u497-facd7e6{padding:5px 8px;border-bottom:1px solid var(--border);color:var(--text2);white-space:nowrap}
.u497-fcb9db8{margin-right:8px;margin-top:3px}
.u497-fdf33f2{margin-bottom:8px}
.u497-fe7b497{margin-top:6px}

/* Tarea 489/497 (fix post-migracion, 2026-09-12): #fSprintCliente y #inpProximosDias
   viven dentro de .search-bar, cuyo selector ".search-bar input{width:340px;...}"
   tiene mas especificidad (clase+elemento) que una sola clase u497-*. Con el style=""
   original (maxima especificidad) esto no era un problema; migrado a clase, la regla
   generica del contenedor gana y estos 2 campos se ensanchaban a 340px sin avisar.
   Se fuerza por ID (mayor especificidad que ".search-bar input") para igualar el
   valor real de main. Ver regla operativa nueva sobre migraciones style=""->clase. */
#fSprintCliente{width:150px;max-width:100%;padding:7px 12px;font-size:13px}
#inpProximosDias{width:36px;padding:2px 4px;font-size:11px;border:1px solid var(--border);border-radius:4px}

/* Tarea 489/497 (fix post-migracion 2, 2026-09-12): misma familia de bug que arriba pero
   contra la regla base "select,input[type=number],input[type=text]{padding:5px 9px;
   font-size:12px;border-radius:6px;...}" (linea ~95), que tiene la MISMA especificidad
   que una clase u497-* sola para <input type=number> / <input type=text> (element+attr
   vs clase = empate 0-1-1 vs 0-1-0 -> en realidad el atributo gana por ser mas especifico).
   Afecta a: #inpProximosDiasMT (Mis Actividades, el caso reportado), #mNombreEdit,
   #relSearchInput, #jPadreSearchInput (diferencias de 1px, poco visibles) y al input
   dinamico "editNotaTexto_"+id (sin ID fijo -> se refuerza por seletor input+clase, que
   empata en especificidad con la regla base y gana por ir despues en el CSS). */
#inpProximosDiasMT{width:38px;padding:1px 4px;font-size:11px;border:1px solid var(--border);border-radius:4px}
#mNombreEdit{font-size:12.5px}
#relSearchInput{padding:5px 8px}
#jPadreSearchInput{padding:5px 8px}
input.u497-4bcf1be{padding:6px 10px;font-size:13px}


/* Tarea 489/497 (Fase A, elementos con patron display:none + reveal-por-vaciado -- ver regla
   operativa 21): estas 2 clases se combinan siempre con .d-none (definida arriba). */
.u497-7664778{width:auto;padding:5px 12px;font-size:11.5px;background:var(--surface2);color:var(--text2)}
.u497-1bdbedf{background:#dc2626;color:#fff;margin-left:6px;vertical-align:middle}

.u497-f152bde{background:#2563eb;color:#fff}

.u497-15c8d3b{width:auto;padding:4px 10px;font-size:11px;background:var(--surface2);color:var(--text2)}
