/* Inter auto-alojada en static/fonts: la app sigue funcionando sin red.
   Solo los pesos que usa la hoja (400, 600, 700 y 800) más 400 cursiva,
   que es lo único que se escribe en cursiva de verdad ("Guardado"). */
@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:swap;
  src:url("/static/fonts/inter-latin-400-normal.woff2") format("woff2")}
@font-face{font-family:Inter;font-style:normal;font-weight:600;font-display:swap;
  src:url("/static/fonts/inter-latin-600-normal.woff2") format("woff2")}
@font-face{font-family:Inter;font-style:normal;font-weight:700;font-display:swap;
  src:url("/static/fonts/inter-latin-700-normal.woff2") format("woff2")}
@font-face{font-family:Inter;font-style:normal;font-weight:800;font-display:swap;
  src:url("/static/fonts/inter-latin-800-normal.woff2") format("woff2")}
@font-face{font-family:Inter;font-style:italic;font-weight:400;font-display:swap;
  src:url("/static/fonts/inter-latin-400-italic.woff2") format("woff2")}
:root{
  --bg:#f4f6fa; --card:#fff; --ink:#1b2432; --mut:#64748b;
  --brand:#0f4c81; --brand2:#1373b5; --ok:#15803d; --mid:#b45309; --bad:#b91c1c;
  --line:#e2e8f0; --radius:14px;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.5 Inter,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif}
/* Los controles de formulario no heredan la fuente en todos los navegadores:
   por eso los botones salían en Arial mientras el resto iba en Inter. */
button,input,select,textarea{font-family:inherit}
a{color:var(--brand2)}
.topbar{position:sticky;top:0;z-index:10;display:flex;gap:1.2rem;align-items:center;
  background:var(--brand);color:#fff;padding:.6rem 1.2rem}
.topbar a{color:#fff;text-decoration:none}
.brand{font-weight:800;font-size:1.15rem}
.brand span{font-weight:400;opacity:.8;font-size:.85rem;margin-left:.4rem}
.topbar nav{display:flex;gap:.4rem;margin-left:1rem}
.topbar nav a{padding:.35rem .8rem;border-radius:999px;opacity:.85}
.topbar nav a.on,.topbar nav a:hover{background:rgba(255,255,255,.18);opacity:1}
.who{margin-left:auto;font-size:.85rem;opacity:.9}
.wrap{max-width:1180px;margin:1.2rem auto 3rem;padding:0 1rem}
/* El pie apila el estado de la carga y el aviso legal, ambos centrados. */
.foot{display:flex;flex-direction:column;align-items:center;gap:.3rem;
  text-align:center;color:var(--mut);font-size:.8rem;padding:1.6rem 2rem}
.foot .foot-estado{color:var(--ink);font-weight:600}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:1.2rem;box-shadow:0 1px 3px rgba(15,76,129,.06)}
h1{font-size:1.5rem;margin:.4rem 0} h2{font-size:1.1rem;margin:1.4rem 0 .7rem}
.muted{color:var(--mut)} .small{font-size:.83rem} .mono{font-family:ui-monospace,Consolas,monospace;font-size:.88em}
.num{text-align:right;font-variant-numeric:tabular-nums}
.kpis{display:flex;gap:.7rem;flex-wrap:wrap;margin:1rem 0}
.kpi{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:.7rem 1rem;min-width:130px}
.kpi b{font-size:1.3rem;display:block} .kpi span{color:var(--mut);font-size:.8rem}
.kpi.warn b{color:var(--mid)}
.kpi.alert{border-color:var(--bad);background:#fef2f2}
.kpi.alert b{color:var(--bad)}
.kpi.alert span{color:var(--bad)}
.hero{background:linear-gradient(120deg,#0b3a63 0%,var(--brand) 45%,var(--brand2) 100%);color:#fff;
  border-radius:18px;padding:1.4rem 1.6rem;margin:1rem 0;box-shadow:0 8px 24px rgba(15,76,129,.3);
  position:relative;overflow:hidden}
.hero::before{content:"";position:absolute;inset:0;
  background:radial-gradient(600px 200px at 85% -40%,rgba(255,255,255,.22),transparent 70%);pointer-events:none}
.hero-mark{position:absolute;right:.6rem;bottom:-1.6rem;font-size:6.5rem;font-weight:800;
  color:rgba(255,255,255,.12);letter-spacing:.02em;pointer-events:none;user-select:none}
/* En pantallas estrechas la marca pisaría los KPI: se va. */
@media(max-width:900px){.hero-mark{display:none}}
.hero h2{margin:.4rem 0 .3rem;font-size:2.1rem;font-weight:800;letter-spacing:-.02em;
  text-shadow:0 2px 10px rgba(0,0,0,.25)}
/* Texto secundario sobre el gradiente: mínimo .92 de opacidad, que es lo
   que garantiza 4,5:1 incluso en el tramo más claro (#1373b5). El ancho
   máximo mantiene la línea por debajo de 70 caracteres y garantiza que el
   texto nunca alcance la esquina más clara del gradiente. */
.hero .muted{color:rgba(255,255,255,.92);max-width:46rem}
/* Título a la izquierda, horas FT / reales / hitos a la derecha. La regla
   estaba en el repo base y se borró junto con `.hero-eyebrow`: sin ella
   `.hero-top` es un div normal y las cifras caían debajo del título, pegadas
   a la izquierda. El `margin-left:auto` las mantiene a la derecha aunque la
   fila se rompa en pantallas estrechas (ahí `space-between` no basta). */
.hero-top{display:flex;justify-content:space-between;gap:1.5rem;flex-wrap:wrap;align-items:flex-start}
.hero-nums{display:flex;gap:1.4rem;flex-wrap:wrap;margin-left:auto}
.hero-nums b{font-size:1.5rem;display:block} .hero-nums span{font-size:.8rem;opacity:.92}
/* Los porcentajes de avance viven AQUÍ, una sola vez: relleno = real,
   marca vertical = programa teórico a hoy. */
.hero-cmp{margin-top:.9rem;max-width:640px}
/* Cada etiqueta cuelga de su elemento dentro de la propia pista. `clamp`
   impide que se salga del contenedor cuando el dato se acerca a 0 o a 100. */
.cmp-track{position:relative;padding-top:1.65rem}
.cmp-tag{position:absolute;white-space:nowrap;font-size:.72rem;font-weight:800;
  letter-spacing:.02em;font-variant-numeric:tabular-nums}
.cmp-tag.teor{top:0;transform:translateX(-50%);color:#fcd34d}
.cmp-tag.teor::before{content:"";display:inline-block;width:.26rem;height:.72rem;
  border-radius:1px;background:#f59e0b;margin-right:.32rem;vertical-align:-1px}
.cmp-under{position:relative;padding-top:1.05rem}
.cmp-tag.real{top:0;color:#fff}
.cmp-tag.real::before{content:"";display:inline-block;width:.55rem;height:.55rem;
  border-radius:2px;background:#fff;margin-right:.32rem;vertical-align:-1px}
.cmp-scale{display:flex;justify-content:space-between;font-size:.65rem;
  letter-spacing:.06em;color:rgba(255,255,255,.92)}
.cmp-note{margin:.5rem 0 0;font-size:.74rem;color:rgba(255,255,255,.92)}
/* Pista propia del avance de hitos, con su etiqueta a la izquierda y su
   cifra a la derecha: no se queda en un dato más del bloque de arriba. */
.cmp-hit{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:.7rem;
  align-items:center;margin-top:.65rem;max-width:640px}
.cmp-hit-k{font-size:.74rem;font-weight:700;color:rgba(255,255,255,.95);white-space:nowrap}
.cmp-hit-k i{font-style:normal}
.cmp-hit-v{font-size:.95rem;color:#fff;font-variant-numeric:tabular-nums}
/* El hero es oscuro: en él los acentos claros, no los de la paleta clara. */
.hero .bad-t{color:#fecaca} .hero .mid-t{color:#fef3c7}
.brows{display:flex;flex-direction:column;gap:.6rem}
.brow{display:grid;grid-template-columns:220px 1fr 230px;gap:1.2rem;align-items:center;
  background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:.8rem 1.1rem;text-decoration:none;color:inherit;transition:transform .08s,box-shadow .08s}
.brow:hover{transform:translateY(-1px);box-shadow:0 6px 18px rgba(15,76,129,.12)}
.brow:focus-visible{outline:2px solid var(--brand2);outline-offset:2px}
.brow-id{display:flex;flex-direction:column;gap:.3rem;align-items:flex-start;font-size:1.05rem}
.brow-nums{display:flex;gap:1.1rem;align-items:center;justify-content:flex-end;
  font-size:.9rem;white-space:nowrap;flex-wrap:wrap}
.brow-nums .go{font-size:1.4rem;color:var(--brand2);font-weight:800}
/* `.brow.compact` es más específico que `.brow`: hay que nombrarlo en la
   media query para que también se apile en móvil. */
.brow.compact{grid-template-columns:230px 1fr auto;padding:.5rem 1rem;gap:1rem}
.brow.compact .brow-id{flex-direction:column;align-items:flex-start;gap:.3rem;font-size:.98rem}
.brow-line{display:flex;align-items:center;gap:.45rem;flex-wrap:wrap}
.brow.compact .brow-nums{gap:.9rem;font-size:.88rem}
/* La media query va DESPUÉS de `.brow.compact`: misma especificidad, gana
   el orden. Si se coloca antes, la regla compacta la pisa y las filas no
   se apilan nunca en móvil. */
@media(max-width:800px){
  .brow,.brow.compact{grid-template-columns:1fr}
  .brow-nums{justify-content:flex-start}
}
.legend{display:flex;gap:.4rem;align-items:center;margin:.1rem 0 .6rem;flex-wrap:wrap}
.sw{display:inline-block;width:14px;height:8px;border-radius:4px}
.sw.real{background:var(--brand2)} .sw.teor{background:#94a3b8} .sw.kg{background:var(--ok)} .sw.av{background:var(--ok)} .sw.plan{background:var(--mid)} .sw.prev{background:repeating-linear-gradient(90deg,var(--mid) 0 3px,transparent 3px 5px)}
.hitos-key{color:var(--ok);font-weight:700}
.table-fold{margin-top:1.2rem}
.table-fold summary{cursor:pointer;list-style:none}
.table-fold summary::-webkit-details-marker{display:none}
.table-fold summary .fold-t{display:inline-block;font-size:1.1rem;font-weight:700;margin:1.4rem 0 .7rem}
.table-fold summary .fold-t::before{content:"› ";color:var(--brand2);font-weight:800}
.table-fold[open] summary .fold-t::before{content:"⌄ "}
.pgrupo{margin-bottom:2rem}
.pgrupo:last-of-type{margin-bottom:0}
.pill{font-size:.72rem;font-weight:700;padding:.15rem .6rem;border-radius:999px;background:#e2e8f0;color:#334155}
.pill.ok{background:#dcfce7;color:var(--ok)} .pill.mid{background:#fef3c7;color:var(--mid)} .pill.bad{background:#fee2e2;color:var(--bad)}
.pill.ghost{background:#e0f2fe;color:var(--brand)}
button.danger{background:var(--bad)} button.danger.small{padding:.2rem .6rem;font-size:.8rem}
/* --- Pista de avance: relleno = real, filete = teórico ------------------- */
.track{position:relative;height:8px;border-radius:999px;background:#e8eef5;overflow:hidden}
.track-fill{display:block;height:100%;border-radius:999px;background:var(--brand2)}
/* El ámbar del teórico tiene el mismo tono que el relleno azul (1:1): un
   halo blanco lo separa del relleno y, sobre la pista clara, el ámbar solo
   ya da 4,3:1. En el hero el halo es azul marino por ser el fondo oscuro. */
.track-mark{position:absolute;top:0;bottom:0;width:4px;margin-left:-2px;
  background:var(--mid);box-shadow:0 0 0 1.5px rgba(255,255,255,.92)}
.track.big{height:14px}
/* Segunda pista: el avance de hitos. Verde sobre pista clara (4,3:1). */
.track.hit .track-fill{background:var(--ok)}
.hero .track{background:rgba(255,255,255,.18)}
.hero .track-fill{background:#fff}
.hero .track-mark{background:#f59e0b;box-shadow:0 0 0 1.5px #0b3a63}
/* Sobre el héroe el verde oscuro no da contraste, igual que le pasa al
   ámbar: mismo tono, versión clara. La pista de esta barra es oscura
   (negro .65) en vez de la clara de arriba: verde sobre pista clara no
   llega a 3:1 en ningún punto del gradiente. Con pista oscura el relleno
   da 9,7:1 y el hueco se lee contra el fondo del héroe 1,59:1, que es lo
   mismo que hace la pista de horas de arriba (1,56–1,69:1). */
.hero .track.hit{background:rgba(0,0,0,.65)}
.hero .track.hit .track-fill{background:#4ade80}
.hero .hitos-key{color:#4ade80}
/* --- Leyenda pegada a las filas: cada ítem enseña el elemento aislado --- */
.track-legend{display:flex;gap:1.1rem;align-items:center;flex-wrap:wrap;
  margin:.1rem 0 .55rem;color:var(--mut)}
.track-legend b{color:var(--ink);font-weight:700}
.tl-i{display:inline-flex;align-items:center;gap:.4rem}
/* Miniatura de la pista con UN solo elemento dentro: el relleno y el filete
   se reconocen porque son literalmente los mismos que la barra de abajo. */
.tl-bar{position:relative;display:inline-block;width:34px;height:8px;flex:0 0 auto;
  border-radius:999px;background:#e8eef5}
.tl-fill{position:absolute;left:0;top:0;bottom:0;width:55%;
  border-radius:999px;background:var(--brand2)}
.tl-fill.hit{background:var(--ok)}
.tl-mark{position:absolute;top:-2px;bottom:-2px;left:50%;width:4px;margin-left:-2px;
  background:var(--mid);box-shadow:0 0 0 1.5px rgba(255,255,255,.92)}
.tl-esc{margin-left:auto;font-size:.72rem}
/* Dos pistas apiladas: horas arriba, hitos debajo. */
.brow-track{min-width:0;display:flex;flex-direction:column;gap:.3rem}
/* Sin horas cargadas: no es atraso, es que aún no hay datos que evaluar.
   El gris neutro es el mismo contraste que los bordes de estado (4,8:1). */
.brow.risk-none{border-left-color:#64748b}
.table-wrap{overflow-x:auto;background:var(--card);border:1px solid var(--line);border-radius:var(--radius)}
table{width:100%;border-collapse:collapse;font-size:.9rem}
th,td{padding:.5rem .7rem;border-bottom:1px solid var(--line);text-align:left;white-space:nowrap}
thead th{background:#eef3f8;position:sticky;top:0}
tbody tr:nth-child(even){background:#f8fafc}
tr.total td{font-weight:800;background:#eef3f8}
.bad-t{color:var(--bad);font-weight:700} .mid-t{color:var(--mid);font-weight:700} .ok-t{color:var(--ok);font-weight:700}
.btn{display:inline-block;background:var(--brand);color:#fff!important;border-radius:8px;padding:.45rem .9rem;text-decoration:none;border:0;cursor:pointer}
.btn.small{padding:.2rem .6rem;font-size:.8rem}
button{background:var(--brand);color:#fff;border:0;border-radius:8px;padding:.55rem 1rem;cursor:pointer;font-size:.95rem}
button:hover{background:var(--brand2)}
input,select{border:1px solid var(--line);border-radius:8px;padding:.5rem .6rem;font-size:.92rem;background:#fff}
label{display:grid;gap:.25rem;margin:.6rem 0;font-size:.9rem}
.filters{display:flex;gap:.5rem;flex-wrap:wrap;margin:.8rem 0}
.flash{background:#e0f2fe;border:1px solid #7dd3fc;border-radius:10px;padding:.6rem .9rem}
.err{background:#fee2e2;color:var(--bad);border-radius:8px;padding:.5rem .8rem}
.empty{background:var(--card);border:1px dashed var(--line);border-radius:var(--radius);padding:2rem;text-align:center}
.crumbs{color:var(--mut);font-size:.88rem}
.bhero{display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;align-items:flex-start}
.bhero h1{margin:0}
.sel-bloque{display:flex;gap:.3rem;flex-wrap:wrap;margin:.8rem 0}
.sel-bloque a{border:1px solid var(--line);background:#fff;border-radius:8px;padding:.25rem .6rem;text-decoration:none;color:var(--ink);font-size:.85rem}
.sel-bloque a.on{background:var(--brand);color:#fff;border-color:var(--brand)}
.inline-edit{display:flex;gap:.25rem}
.inline-edit input{width:64px;padding:.25rem .4rem;font-size:.82rem}
.inline-edit button{padding:.25rem .5rem}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:.8rem}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:.8rem}
@media(max-width:1000px){.grid3{grid-template-columns:1fr 1fr}}
@media(max-width:800px){.grid2,.grid3{grid-template-columns:1fr}.topbar nav{margin-left:0}.who{display:none}}
.subnav{position:sticky;top:3.4rem;z-index:5;display:flex;gap:.5rem;flex-wrap:wrap;
  background:var(--bg);padding:.5rem 0;margin-bottom:.4rem}
.subnav a{border:1px solid var(--line);background:var(--card);border-radius:999px;padding:.3rem .9rem;
  text-decoration:none;color:var(--ink);font-size:.85rem;font-weight:600}
.subnav a:hover{border-color:var(--brand2);color:var(--brand)}
.group-title{margin:1.6rem 0 .7rem;padding-top:.6rem;border-top:2px solid var(--line)}
.card h3{font-size:1rem;margin:.2rem 0 .7rem}
.card h3.inline{display:inline-block}
/* .btn-ghost-danger está más abajo, con el mismo estilo que usa la ficha
   de bloque: una sola definición para que guardar y borrar se vean igual. */
.btn-danger{background:var(--bad);color:#fff;border:1px solid var(--bad);border-radius:8px;
  padding:.45rem .9rem;cursor:pointer;font-size:.9rem}
.btn-danger:hover{background:#991b1b;border-color:#991b1b}
button.btn-danger{color:#fff}
/* Con `.btn small` el borde de 1px lo desalinea 2px respecto a Editar o
   Cerrar, que van con border:0. El borde es del mismo color que el fondo,
   así que no aporta nada. */
.btn.btn-danger{border-width:0}
.table-wrap.tall{max-height:340px;overflow-y:auto}
details summary{cursor:pointer}
details summary h3.inline::before{content:"› ";color:var(--brand2);font-weight:800}
details[open] summary h3.inline::before{content:"⌄ "}
.modal-overlay{display:none;position:fixed;inset:0;z-index:50;background:rgba(15,30,50,.55);
  align-items:flex-start;justify-content:center;overflow-y:auto;padding:3rem 1rem}
.modal-overlay.open{display:flex}
.modal-box{position:relative;background:var(--card);border-radius:18px;max-width:760px;width:100%;
  padding:1.4rem 1.6rem;box-shadow:0 20px 60px rgba(0,0,0,.35)}
.modal-box.wide{max-width:1040px}
.nb-bar{display:flex;gap:1rem;align-items:center;margin:.4rem 0 .6rem}
.nb-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:.35rem}
.nb-item{display:flex;gap:.45rem;align-items:center;border:1px solid var(--line);border-radius:8px;
  padding:.32rem .5rem;font-size:.82rem;cursor:pointer;background:#fff}
.nb-item:has(.nb-aplica:checked){border-color:var(--brand2);background:#f0f7fd}
.nb-item .mono{font-size:.85em;white-space:nowrap}
.nb-desc{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--mut);min-width:0}
.nb-item .nb-pct{width:62px;padding:.25rem .35rem;font-size:.85rem;margin-left:auto;flex:none}
@media(max-width:640px){.nb-grid{grid-template-columns:repeat(auto-fill,minmax(160px,1fr))}}
.modal-close{position:absolute;top:.6rem;right:.8rem;background:none;border:0;color:var(--mut);
  font-size:1.8rem;line-height:1;cursor:pointer;padding:.2rem .5rem}
.modal-close:hover{color:var(--bad)}
.modal-head{background:linear-gradient(120deg,#0b3a63 0%,var(--brand) 55%,var(--brand2) 100%);
  margin:-1.2rem -1.4rem 1rem;padding:.9rem 1.4rem;border-radius:12px 12px 0 0;
  display:flex;align-items:center;justify-content:space-between}
.modal-head h3{margin:0;color:#fff;font-size:1.2rem}
.modal-head .modal-close{position:static;color:rgba(255,255,255,.9)}
.modal-head .modal-close:hover{color:#fff}
button:disabled{opacity:.45;cursor:not-allowed}
.login-body{min-height:100vh;display:grid;place-items:center;background:linear-gradient(135deg,var(--brand),var(--brand2))}
.login{width:min(380px,92vw)} .login h1{margin:0} .login button{width:100%}
.chk{grid-auto-flow:column;grid-template-columns:auto 1fr;align-items:center}
.pager{display:flex;gap:1rem;align-items:center;margin:.8rem 0}
/* ---- Ficha bloque compacta ---- */
.blk-top{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem;flex-wrap:wrap}
.blk-top h1{display:inline;font-size:1.25rem;margin:0 .4rem 0 0}
.blk-top .sel-bloque{margin:.1rem 0}
.kpis.mini{gap:.4rem;margin:.45rem 0}
.kpis.mini .kpi{padding:.3rem .6rem;min-width:88px;flex:1 1 0;text-align:center}
.kpis.mini .kpi b{font-size:.95rem}
.kpis.mini .kpi span{font-size:.66rem}
.card.flat{padding:.6rem .8rem}
.card.flat svg{display:block;width:calc(100% - 1.6rem)!important;margin:0 auto}
.card.flat h2{margin:0 0 .35rem;font-size:.9rem}
.wrap:has(.blk){max-width:1560px}
.blk-scroll{overflow-x:auto}
.blk-grid3{display:grid;grid-template-columns:minmax(560px,1.5fr) minmax(320px,1fr) minmax(280px,.9fr);gap:.6rem;margin:.5rem 0;align-items:start;min-width:1240px}
.blk-grid2h{display:grid;grid-template-columns:minmax(440px,1fr) minmax(440px,1fr);gap:.6rem;margin:.5rem 0;align-items:start;min-width:940px}
.blk-grid1{display:grid;grid-template-columns:minmax(600px,1fr);gap:.6rem;margin:.5rem 0;align-items:start}
.blk-grid3t{display:grid;grid-template-columns:minmax(440px,1.25fr) minmax(440px,1.25fr) minmax(315px,.735fr);gap:.6rem;margin:.5rem 0;align-items:stretch;min-width:1195px}
.blk-grid3t>.card{align-self:stretch}
/* La tarjeta de Pesos estira su tabla hasta el fondo de la caja. */
.blk-grid3t>.pesos-card{display:flex;flex-direction:column}
.blk-grid3t>.pesos-card>h2,.blk-grid3t>.pesos-card>p{flex:0 0 auto}
.blk-grid3t>.pesos-card .table-wrap{flex:1 1 auto;min-height:0}
.blk-grid3t>.pesos-card table{height:100%}
.blk-side{display:flex;flex-direction:column;gap:.6rem}
.blk-grid{display:grid;grid-template-columns:7fr 5fr;gap:.6rem;margin:.5rem 0}
.blk-cols{display:grid;grid-template-columns:1fr 1fr;gap:.6rem}
button.exp{background:none;border:0;cursor:pointer;color:var(--brand2);font-size:.8rem;padding:0 .2rem}
tr.subrow td{background:#f6f9fc}
tr.subrow td.mono.sub{padding-left:1.1rem;color:var(--brand2)}
table.sub td{font-size:.68rem;padding:.1rem .3rem}
table.dense{font-size:.7rem}
table.dense th,table.dense td{padding:.14rem .35rem}
td.cut{max-width:150px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media(max-width:820px){.blk-grid,.blk-cols,.blk-side{grid-template-columns:1fr}}
/* ---- Dashboard UX ---- */
/* El título del grupo pasa a h3 (h1 = página, h2 = programa): hay que
   devolverle el tamaño y los márgenes que le daba la regla global de h2. */
.bbarco>h3{display:flex;align-items:center;gap:.5rem;background:#eef4fa;border-left:4px solid var(--brand2);
  border-radius:0 var(--radius) var(--radius) 0;padding:.45rem .8rem;
  font-size:1.1rem;font-weight:700;margin:1.4rem 0 .7rem}
.bbarco{margin-bottom:1.4rem}
.brow{border-left:4px solid var(--ok)}
.brow.risk-bad{border-left-color:var(--bad)} .brow.risk-mid{border-left-color:var(--mid)}
.brow-nums b{font-variant-numeric:tabular-nums}
/* ---- Gantt ---- */
.g-scroll{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);background:#fff}
.g-grid{position:relative;min-width:1100px}
.g-row{display:flex;border-bottom:1px solid var(--line);min-height:34px}
.g-lab{flex:0 0 280px;max-width:280px;padding:.3rem .6rem;font-size:.8rem;overflow:hidden;
  background:#fff;position:sticky;left:0;z-index:3;border-right:1px solid var(--line)}
.g-track{flex:1;position:relative;min-height:34px;background:#fff}
.g-head .g-track{background:#eef3f8}
.g-seg{position:absolute;top:0;bottom:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;
  border-left:1px solid var(--line);font-size:.68rem;color:#64748b;padding:.1rem .3rem}
.g-mes{font-weight:700;background:#eef3f8;height:50%}
.g-sem{top:50%;height:50%;background:#f6f9fc}
.g-finde{position:absolute;top:0;bottom:0;background:#f1f5f9}
.g-prog{position:absolute;top:0;bottom:0;background:rgba(19,115,181,.07);border-left:1px dashed #94a3b8;border-right:1px dashed #94a3b8}
.g-resumen{position:absolute;top:11px;height:12px;background:#e2e8f0;border-radius:6px;overflow:hidden}
.g-resumen i{display:block;height:100%;background:#94a3b8}
.g-bar{position:absolute;top:7px;height:20px;border-radius:5px;overflow:hidden;
  background-image:linear-gradient(180deg,rgba(255,255,255,.35),rgba(255,255,255,0) 45%,rgba(0,0,0,.18));
  box-shadow:0 2px 5px rgba(15,40,60,.35),inset 0 0 0 1px rgba(0,0,0,.12)}
.g-bar.retr{outline:2px solid var(--bad);outline-offset:1px}
.g-bar.jhito{cursor:pointer}
.g-bar.sel{outline:2px solid var(--brand2);outline-offset:1px}
.g-fill{display:block;height:100%;background:rgba(0,0,0,.30)}
.g-grupo .g-track{background:linear-gradient(180deg,#fbfdff,#f1f5f9)}
.g-grupo .g-lab{background:linear-gradient(180deg,#fbfdff,#f1f5f9)}
.g-dot{display:inline-block;width:.6rem;height:.6rem;border-radius:50%;margin-right:.35rem}
.g-diam{position:absolute;top:4px;transform:translateX(-50%);color:var(--mid);font-size:.9rem;z-index:2;pointer-events:auto}
td.hito-hoy{background:#fef9e7 !important;outline:2px solid var(--mid);outline-offset:-2px}
/* ---- Hitos (vista mensual gráfica) ---- */
.hitos-bar{display:flex;align-items:center;gap:1rem;flex-wrap:wrap}
.hitos-bar h1{margin:.2rem 0}
.hitos-vista{display:inline-flex;gap:.25rem}
/* `.btn` fuerza color:#fff con !important (línea 174) y se lo comía a todas
   las variantes ghost: texto blanco sobre azul claro o sobre blanco, es
   decir, invisible. El !important aquí es lo único que puede ganarle. */
.btn-ghost{background:#dbe7f3;color:var(--brand)!important;border:1px solid #bcd3e6}
.btn-ghost:hover{background:#c9dcee;border-color:var(--brand2)}
.hitos-nav{display:flex;align-items:center;gap:.6rem;margin:.4rem 0 .6rem;flex-wrap:wrap}
.hitos-nav b{text-transform:capitalize;font-size:1.15rem}
.hitos-legend{display:flex;align-items:center;gap:.9rem;flex-wrap:wrap;margin-bottom:.5rem}
.hitos-grid{border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;background:#fff}
.hitos-dow{display:grid;grid-template-columns:repeat(7,minmax(0,1fr))}
.hitos-week{display:block}
.hitos-dow span{background:#0f4c81;color:#fff;font-size:.72rem;font-weight:700;text-transform:uppercase;
  letter-spacing:.04em;padding:.4rem .5rem;text-align:center}
.hitos-week{border-top:1px solid var(--line)}
.hitos-days{display:grid;grid-template-columns:repeat(7,minmax(0,1fr))}
.hitos-lanes{position:relative;padding:0 0 3px}
.hitos-teo{position:absolute;transform:translateX(-50%);color:var(--mid);font-size:.85rem;z-index:2}
.hitos-day{min-height:30px;padding:.2rem .3rem;border-left:1px solid var(--line);
  font-size:.75rem;background:#fff}
.hitos-day:first-child{border-left:0}
.hitos-day.finde{background:#f6f8fb}
.hitos-day.fuera{opacity:.45}
.hitos-day.hoy{outline:2px solid var(--bad);outline-offset:-2px;background:#fff7f7}
.hitos-num{display:inline-block;min-width:1.5rem;text-align:center;font-weight:800;font-size:.8rem;
  border-radius:50%;padding:.05rem .2rem;margin-bottom:.2rem}
.hitos-day.hoy .hitos-num{background:var(--bad);color:#fff}
.hito{position:absolute;display:flex;align-items:center;gap:.25rem;height:20px;
  background:#f1f5f9;background:color-mix(in srgb,var(--c,#64748b) 16%,#fff);
  border-left:4px solid var(--c,#64748b);
  border-radius:4px;padding:.1rem .3rem;font-size:.72rem;font-weight:600;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.hito i{font-style:normal;opacity:.55}
.hito b{color:var(--bad)}
.hito.fin{opacity:.55;text-decoration:line-through}
.hito.splan{background:#fff;background:color-mix(in srgb,var(--c,#64748b) 8%,#fff);
  border:1px dashed var(--c,#64748b);border-left:4px solid var(--c,#64748b)}
.hito{cursor:pointer}
.hito.sel{outline:2px solid var(--brand2);outline-offset:1px;background:#e0f2fe}
/* ---- Hitos en ficha ---- */
/* Pestañas: una por subbloque + bloque. */
.hito-tabs{display:flex;gap:.3rem;flex-wrap:wrap;margin:.5rem 0 .2rem;
  border-bottom:1px solid var(--line);padding-bottom:.35rem}
.hito-tab{border:1px solid var(--line);background:#f4f8fc;border-radius:20px;
  padding:.22rem .7rem;font-size:.78rem;font-weight:700;color:#475569;cursor:pointer}
.hito-tab:hover{border-color:var(--brand2);color:var(--brand)}
.hito-tab.on{background:var(--brand2);border-color:var(--brand2);color:#fff}
.hito-tab b{display:inline-block;min-width:1.1rem;margin-left:.25rem;padding:0 .25rem;
  border-radius:10px;background:rgba(0,0,0,.08);font-size:.68rem}
.hito-tab.on b{background:rgba(255,255,255,.25)}
.hitos-vacio{padding:.8rem 0}
.hito-row{border:1px solid var(--line);border-left:5px solid var(--brand2);border-radius:10px;
  padding:.6rem .8rem;margin:.5rem 0;background:#fff}
.hito-row.late{border-left-color:var(--bad)}
.hito-row.done{border-left-color:var(--ok);background:#fbfefb}
.hito-head{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
.hito-head b{font-size:1.02rem}
.hito-badge{font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.05em;
  border-radius:20px;padding:.15rem .6rem;background:#eef3f8;color:var(--brand)}
.hito-row.late .hito-badge{background:#fee2e2;color:var(--bad)}
.hito-row.done .hito-badge{background:#dcfce7;color:var(--ok)}
.pill.sb{background:#e0f2fe;color:var(--brand);font-weight:700}
.pbar{position:relative;height:22px;background:#eef3f8;border-radius:11px;overflow:hidden;margin:.45rem 0 .3rem}
.pbar i{display:block;height:100%;background:linear-gradient(90deg,var(--brand2),#4aa3df)}
.hito-row.late .pbar i{background:linear-gradient(90deg,var(--bad),#e26d6d)}
.hito-row.done .pbar i{background:linear-gradient(90deg,var(--ok),#4ade80)}
.pbar.horas i{background:linear-gradient(90deg,#b45309,#e8a13c)}
.pbar b{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:.75rem;color:#0f2c44}
.hito-meta{display:flex;gap:1rem;flex-wrap:wrap}
/* Indicadores del hito: etiqueta encima, valor debajo. */
.hito-stats{display:flex;gap:1.15rem;flex-wrap:wrap;align-items:flex-end;margin:.55rem 0 .1rem}
.stat{display:flex;flex-direction:column;gap:.1rem;line-height:1.2}
.stat span{font-size:.62rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--mut)}
.stat b{font-size:.98rem;font-weight:700;color:#0f2c44}
.stat b.bad-t{color:var(--bad)}
/* Valor en una sola línea: así todos los indicadores comparten línea base
   y el "asig." no empuja el valor hacia arriba. */
.stat-v{display:flex;align-items:baseline;gap:.3rem;line-height:inherit}
.stat i{font-size:.63rem;font-style:normal;color:var(--mut)}
/* Solo los oficios que no llegan al fin: el desglose de horas por oficio se
   quitó porque su suma era exactamente «Restan» y ya está en Actividades. */
.hito-oficios{display:flex;gap:.35rem;flex-wrap:wrap;align-items:center;margin:.15rem 0 .2rem}
.of-lab{font-size:.62rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--mut)}
.hito-oficios .of-lab{color:var(--bad)}
.of-chip{font-size:.72rem;line-height:1.35;background:#f4f8fc;border:1px solid var(--line);
  border-radius:20px;padding:.18rem .6rem;color:#475569}
.of-chip b{color:#0f2c44}
.of-chip.late{background:#fee2e2;border-color:#fca5a5;color:var(--bad)}
.of-chip.late b{color:var(--bad)}
.hito-acts{margin-top:.4rem}
.pbar i.av{background:linear-gradient(90deg,var(--ok),#4ade80)}
/* Cada barra va con su rótulo, para que se sepa qué mide. */
.pbar-row{display:flex;align-items:center;gap:.45rem;margin:.45rem 0 .3rem}
.pbar-row>.pbar{flex:1 1 auto;min-width:0;margin:0}
.pbar-lab{flex:0 0 auto;min-width:8.4rem;text-align:left;white-space:nowrap;
  font-size:.66rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--mut)}
.pbar-row.av-row .pbar-lab{color:var(--ok)}
.pbar-row.horas-row .pbar-lab{color:var(--mid)}
.fases{display:flex;gap:.35rem;flex-wrap:wrap;margin:.15rem 0 .35rem}
/* Leyenda de fases a la izquierda y peso en kg a la derecha de la misma fila. */
/* Los márgenes verticales colapsan: para separar de la barra de ritmo hay que
   superar el margin-top de .pbar-row (.45rem), no solo sumar. */
.fases-row{display:flex;align-items:center;gap:.45rem;margin:.1rem 0 .85rem}
.fases-row>.fases{flex:1 1 auto;min-width:0;margin:0}
.kg-hito{flex:0 0 auto;white-space:nowrap;font-size:.72rem;font-weight:700;
  color:var(--mid);background:#fef3c7;border-radius:20px;padding:.2rem .6rem}
.kg-hito.vacio{color:var(--bad);background:#fee2e2;font-weight:600}
.fase-chip{display:inline-flex;align-items:center;gap:.3rem;font-size:.72rem;line-height:1.3;
  border:1px solid var(--line);border-radius:20px;padding:.2rem .6rem;
  background:#f4f8fc;color:#64748b}
.fase-chip b{font-weight:800;color:#94a3b8}
button.fase-chip{cursor:pointer;font-family:inherit}
button.fase-chip:hover{border-color:var(--brand2);color:var(--brand);background:#e0f2fe}
.fase-chip.ok{background:#dcfce7;border-color:#86efac;color:var(--ok)}
.fase-chip.ok b{color:var(--ok)}
.fases-edit{display:flex;flex-wrap:wrap;gap:.4rem;align-items:center;margin:.2rem 0 .6rem}
.fase-row{display:flex;gap:.4rem;align-items:center;border:1px solid var(--line);
  border-radius:8px;padding:.25rem .45rem;background:#f8fafc}
.fase-row input[type=text]{width:11rem}
.fase-row input[type=number]{width:5rem}
.fase-row label{margin:0;white-space:nowrap}
.fases-edit [data-addfase]{align-self:flex-start}
/* ---- Modal ---- */
.modal{display:none;position:fixed;inset:0;background:rgba(15,40,60,.45);z-index:50;
  align-items:center;justify-content:center;overflow-y:auto;padding:1rem 0}
.modal.open{display:flex}
.modal.open .modal-box{margin:auto}
.modal-box{background:#fff;border-radius:12px;padding:1.2rem 1.4rem;min-width:min(92vw,380px);
  box-shadow:0 12px 40px rgba(0,0,0,.3)}
.modal-box h3{margin:.1rem 0 .4rem}
.modal-box label{display:block;margin:.5rem 0}
.modal-box input[type=date]{margin-left:.4rem}
.g-hoy{position:absolute;top:0;bottom:0;border-left:2px solid var(--bad);z-index:2;pointer-events:none}
.g-hoy i{position:absolute;top:0;left:2px;font-size:.65rem;font-style:normal;color:var(--bad);background:#fff;padding:0 .2rem}
.g-bar .h{position:absolute;top:0;bottom:0;width:10px;display:none}
.g-bar .h-l{left:0;cursor:ew-resize} .g-bar .h-r{right:0;cursor:ew-resize}
.g-grid.drag .g-bar{cursor:grab}
.g-grid.drag .g-bar .h{display:block}
.g-grid.drag .g-bar.moviendo{opacity:.75;cursor:grabbing;z-index:4}
#gantt-msg{min-height:1.2em}

/* --- Actividades compartidas entre hitos ----------------------------- */
/* Aviso de FT que no cuadra con lo planificado en los hitos. */
.cov-warn{background:#fffbeb;border:1px solid #fcd34d;border-radius:var(--radius);
  padding:.5rem .7rem;color:#78350f;margin:.3rem 0 .6rem}
.cov-warn b{color:#92400e}
/* Desglose por actividad dentro de la ficha del hito. */
.acts-fold{margin:.3rem 0 .2rem}
.acts-fold summary{cursor:pointer;list-style:none;font-size:.72rem;font-weight:700;
  color:#0f2c44;display:flex;align-items:baseline;gap:.4rem}
.acts-fold summary::-webkit-details-marker{display:none}
.acts-fold summary::before{content:"\203A ";color:var(--brand2);font-weight:800}
.acts-fold[open] summary::before{content:"\2304 "}
.acts-fold .table-wrap{margin-top:.35rem}
/* Marca de actividad compartida: su porción se reparte entre los hitos de su subbloque. */
.tag-comp{display:inline-block;font-size:.6rem;font-weight:800;letter-spacing:.04em;
  color:#1e3a8a;background:#dbeafe;border:1px solid #93c5fd;
  border-radius:4px;padding:0 .3rem;vertical-align:1px}
tr.compartida>td{background:#f8fbff}

/* --- Editar hito: actividades que no se pueden añadir aquí ------------- */
/* Ya están en otro hito del mismo subbloque y no son compartidas: si se
   marcaran, el guardado entero se rechazaría. */
tr.bloq{opacity:.55}
tr.bloq td.mono{white-space:nowrap}
.tag-lock{font-size:.7rem;vertical-align:1px}
input[type=checkbox]:disabled{cursor:not-allowed}
/* Los errores de guardado tienen que verse, no pasar por una nota gris. */
.flash.err{background:#fee2e2;border-color:#fca5a5;color:#7f1d1d;font-weight:600}
/* La columna Oficio va pegada al número de Personal: ancho corto y sin
   estirarse, para que no quede un hueco vacío entre las dos. */
.acts-fold td:last-child{white-space:nowrap}
/* width:1% ajusta la columna al contenido sin repartir el ancho sobrante.
   th y td llevan el MISMO padding para que el rótulo caiga justo encima del
   nombre del oficio. El hueco queda solo a la derecha, hacia Personal. */
.acts-fold th.ofi, .acts-fold td.ofi{width:1%;padding-left:1.15rem;padding-right:.7rem;
  white-space:nowrap}
.acts-fold td:last-child{width:1%;padding-left:.3rem}

/* --- KPIs del bloque, agrupados por lo que sirven para decidir ---------- */
/* Estado = ¿va bien?  Volumen = ¿cuánto hay?  Detalle = el resto. */
.kpis .kpi.grupo{background:none;border:0;padding:0;min-width:0;text-align:left;
  display:flex;flex-direction:column;gap:.3rem}
.kpis .k-lbl{font-size:.62rem;font-weight:800;letter-spacing:.06em;
  text-transform:uppercase;color:var(--mut)}
.kpis .k-fila{display:flex;gap:.5rem;flex-wrap:wrap}
/* `<b>` y `<span>` son inline: sin apilarlos en columna el texto largo parte
   la celda en un número distinto de líneas que el resto y quedan desiguales. */
.kpis .kpi.sub{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:.5rem .8rem;min-width:0;text-align:center;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.1rem}
.kpis .kpi.sub b{font-size:1.1rem;white-space:nowrap}
/* El dato de estado se lee antes que el resto: un poco más grande y con el
   borde marcado cuando el bloque va retrasado. */
.kpis .grupo:first-child .kpi.sub:first-child b{font-size:1.45rem}
.kpis .grupo:first-child .kpi.sub:first-child span{font-size:.78rem;font-weight:700}
/* Los grupos se separan con una regleta vertical, no con más tarjetas. */
.kpis .kpi.grupo + .kpi.grupo{border-left:1px solid var(--line);padding-left:.8rem}
@media(max-width:820px){
  .kpis .kpi.grupo + .kpi.grupo{border-left:0;padding-left:0}
  .kpis .kpi.grupo{padding-top:.4rem}
}

/* --- Dashboard: una sola tira de celdas -------------------------------- */
/* No hay grupo anidado: los labels son marcadores de sección DENTRO de la
   propia tira, con la misma regleta que separa los grupos de la ficha. Las
   celdas van `flex:1 1 0` para que las doce midan exactamente lo mismo. */
.kpis.kpis-tira .k-lbl{display:flex;align-items:center;align-self:center;
  flex:0 0 auto;white-space:nowrap;padding-left:.65rem;margin-left:.2rem;
  border-left:1px solid var(--line)}
/* El primero no lleva línea pero sí conserva el hueco, para que la primera
   celda de cada sección arranche a la misma distancia de su label. */
.kpis.kpis-tira .k-lbl:first-child{border-left:0}
.kpis.kpis-tira .kpi.sub{flex:1 1 0;min-width:96px;padding:.45rem .6rem;gap:.15rem}
/* 12 celdas + 4 labels no caben en los 1180px de `.wrap`: sin este ancho la
   tira se parte en dos filas y las columnas dejan de medir lo mismo. */
.wrap:has(.kpis-tira){max-width:1560px}
@media(max-width:1240px){
  .kpis.kpis-tira .kpi.sub{min-width:0;padding:.4rem .4rem}
  .kpis.kpis-tira .kpi.sub b{font-size:.95rem}
  .kpis.kpis-tira .k-lbl{padding-left:.45rem;margin-left:.1rem}
}
@media(max-width:820px){
  /* Con hueco para las celdas la tira vuelve a envolver en varias filas. */
  .kpis.kpis-tira .kpi.sub{min-width:104px}
  .kpis.kpis-tira .k-lbl{width:100%;border-left:0;padding-left:0;margin:0}
}

/* --- Cabecera de sección y avisos -------------------------------------- */
.sec-cab{display:flex;justify-content:space-between;align-items:baseline;
  gap:1rem;flex-wrap:wrap;margin-bottom:.35rem}
.sec-cab h2{margin:0}
.aviso{display:flex;gap:.4rem;align-items:baseline;background:#fffbeb;
  border:1px solid #fcd34d;border-left:3px solid #f59e0b;border-radius:8px;
  padding:.4rem .65rem;margin:.3rem 0;font-size:.78rem;color:#78350f;line-height:1.45}
.aviso b{color:#92400e}
.aviso b.bad-t{color:var(--bad)}
/* La ayuda de reparto de horas: plegada, a la vista pero sin ocupar. */
.ayuda{margin:.25rem 0 .5rem}
.ayuda summary{cursor:pointer;font-size:.76rem;color:var(--brand2);font-weight:600}
.ayuda summary::before{content:"› ";font-weight:800}
.ayuda[open] summary::before{content:"⌄ "}
.ayuda p{font-size:.78rem;color:var(--mut);line-height:1.5;max-width:78ch;margin:.35rem 0}
.ayuda p b{color:#334155}
/* Los chips y las píldoras del glosario van dentro de un párrafo: hay que
   alinearlos verticalmente con el texto circundante. */
.ayuda .pill,.ayuda .sw{vertical-align:middle;margin:0 .15rem}

/* --- Editor del avance de una fase, dentro del propio chip -------------- */
.fase-chip.editando{display:inline-flex;gap:.2rem;align-items:center;background:#fff;
  border-color:var(--brand2);box-shadow:0 0 0 2px rgba(19,115,181,.12)}
.fase-chip.editando input{font-size:.8rem;padding:.05rem .2rem;text-align:right;
  border:1px solid var(--brand2);border-radius:4px}
.fase-chip.editando input.mal{border-color:var(--bad);background:#fef2f2}
.fase-chip .mini{border:1px solid var(--line);background:#f1f5f9;border-radius:4px;
  cursor:pointer;font-size:.72rem;line-height:1;padding:.12rem .28rem;color:#334155}
.fase-chip .mini:hover{background:#e2e8f0}
.fase-chip .mini.ok{background:#dcfce7;border-color:#86efac;color:#15803d}
.fase-chip .mini.ok:hover{background:#bbf7d0}

/* --- Texto solo para lectores de pantalla (labels de los campos) -------- */
.sro{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* --- Acciones del hito: lo destructivo, aparte ------------------------ */
.hito-acts{display:flex;gap:.4rem;align-items:center;flex-wrap:wrap}
.hito-acts form.borrar-hito{margin-left:auto;padding-left:.9rem;
  border-left:1px solid var(--line)}
.btn-ghost-danger{background:#fff;color:var(--bad)!important;border:1px solid #fecaca}
.btn-ghost-danger:hover{background:#fef2f2;border-color:#f87171}

/* --- La ficha también se usa en pantallas estrechas -------------------- */
/* Las tres tarjetas de arriba se apilan en vez de obligar a arrastrar en
   horizontal; las tablas conservan su propio scroll, que sí funciona. */
@media(max-width:1240px){
  .blk-scroll{overflow-x:visible}
  .blk-grid3t{grid-template-columns:1fr 1fr;min-width:0}
  .blk-grid3t>.pesos-card{grid-column:1 / -1}
  .blk-grid2h{grid-template-columns:1fr;min-width:0}
}
@media(max-width:820px){
  .blk-grid3t{grid-template-columns:1fr}
  .kpis .k-fila{gap:.4rem}
  .kpis .kpi.sub{flex:1 1 auto}
  .hito-acts form.borrar-hito{margin-left:0;padding-left:0;border-left:0;
    width:100%;border-top:1px solid var(--line);padding-top:.4rem;margin-top:.2rem}
}

/* --- Controles con tamaño usable también en táctil -------------------- */
.fase-chip{min-height:1.7rem;display:inline-flex;align-items:center}
.modal .btn.small{min-height:2rem;padding:.3rem .7rem}
.modal input[type=checkbox]{width:1rem;height:1rem}
.modal table.dense input[type=checkbox]{width:1rem;height:1rem}
.modal table.dense td{padding:.3rem .4rem}

/* --- Fila de hito condensada ------------------------------------------- */
/* El peso no se muestra en la cabecera: es el mismo «N h de plan» que lleva
   el desplegable de Actividades, y solo se repetía. */
/* Las dos barras, juntas y distinguibles de un vistazo: avance en azul,
   ritmo en naranja. Antes cada una con su rótulo largo y separadas por los
   chips de fase. */
.hito-row .pbar-row.horas-row{margin:.3rem 0 .1rem}
.hito-row .pbar.av{border:1px solid #cfe3f5}
.hito-row .pbar.horas{border:1px solid #f3d9b0}
/* Una sola línea con las cifras sueltas, en lugar de cinco azulejos. */
.hito-sum{display:flex;gap:1rem;flex-wrap:wrap;align-items:baseline;
  margin:.4rem 0 .2rem;font-size:.75rem;color:var(--mut)}
.hito-sum b{color:#0f2c44;font-size:.85rem}
.hito-sum .bad-t{color:var(--bad)}
.hito-sum .bad-t b{color:var(--bad)}
/* Pie: el desplegable de actividades a la izquierda, las acciones a la derecha. */
.hito-pie{display:flex;justify-content:space-between;align-items:flex-end;
  gap:.8rem;flex-wrap:wrap}
.hito-pie .acts-fold{flex:1 1 auto;min-width:0;margin:.2rem 0}
.hito-pie .hito-acts{flex:0 0 auto;margin-bottom:.15rem}
@media(max-width:820px){
  .hito-pie{flex-direction:column;align-items:stretch}
  .hito-pie .hito-acts{justify-content:flex-start}
}

/* --- Mantenimiento ---------------------------------------------------- */
/* Los tres catálogos comparten fila: ancho mínimo 0 para que la tabla de
   dentro haga scroll en vez de estirar la tarjeta y sus vecinas. */
.grid3>.card{min-width:0}
/* Pie de tarjeta: lo que guarda, a la izquierda; lo que borra, a la derecha
   y aparte. Mismo patrón que el pie de la fila de hito. */
.card-pie{display:flex;justify-content:space-between;gap:.8rem;flex-wrap:wrap;
  align-items:center;margin-top:.8rem;padding-top:.6rem;border-top:1px solid var(--line)}
.card-pie .btn-ghost-danger{margin-left:auto}
.card-pie button{white-space:nowrap}
/* Los dos formularios de Actividades, uno al lado del otro. */
.form2{display:grid;grid-template-columns:1fr 1fr;gap:0 1.4rem}
.form2 .filters{margin:.3rem 0}
/* Título de grupo con su acción a la derecha de la misma línea. */
.sec-head{display:flex;justify-content:space-between;align-items:flex-end;
  gap:1rem;flex-wrap:wrap}
.sec-head .group-title{flex:1 1 auto;margin-bottom:0}
.sec-act{margin:0 0 .7rem}
/* Bolsa e histórico: misma altura. La tarjeta es columna y el formulario de
   la bolsa queda anclado abajo, para que no se quede el hueco en medio. */
.grid2.top{align-items:stretch}
.grid2.top>.card{display:flex;flex-direction:column}
.grid2.top>.card>.filters{margin-top:auto}
/* Diagnóstico: el plegable hace de tarjeta, sin un envoltorio debajo. */
.diag-fold{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:.55rem .9rem;margin:.4rem 0 .9rem}
.diag-fold>summary{cursor:pointer;list-style:none;font-size:.9rem;font-weight:700;
  color:var(--ink);display:flex;align-items:baseline;gap:.4rem}
.diag-fold>summary::-webkit-details-marker{display:none}
.diag-fold>summary::before{content:"\203A ";color:var(--brand2);font-weight:800;font-size:1.05rem}
.diag-fold[open]>summary::before{content:"\2304 "}
.diag-fold[open]>summary{margin-bottom:.5rem;padding-bottom:.4rem;
  border-bottom:1px solid var(--line)}
.diag-fold p{margin:.4rem 0 .7rem}
@media(max-width:900px){.form2{grid-template-columns:1fr}}

/* --- /semanales: resumen semanal por OT --------------------------------- */
/* Barra de totales del filtro activo, encima de la tabla. */
.sem-tot{display:flex;flex-wrap:wrap;gap:.3rem 1.1rem;align-items:baseline;
  background:#f8fafc;border:1px solid var(--line);border-radius:10px;
  padding:.5rem .8rem;margin:.35rem 0 .6rem;font-size:.8rem;color:#475569}
.sem-tot b{color:var(--ink);font-variant-numeric:tabular-nums}
/* Reparto MOD/MOI/Otra de una fila: dos líneas, sin empujar la tabla. */
.sem-rep{font-size:.7rem;line-height:1.6;white-space:normal;color:#475569}
.sem-rep b{color:var(--ink);font-variant-numeric:tabular-nums}
.sem-comp{font-size:.7rem;white-space:normal;color:#475569}
.sem-est{display:flex;flex-wrap:wrap;gap:.2rem}
/* Desplegable con actividades y posiciones de la fila. Va en línea (no en
   overlay): así no lo recorta el scroll horizontal de .table-wrap. */
.sem-det summary{cursor:pointer;list-style:none;font-size:.7rem;font-weight:700;
  color:var(--brand2);display:flex;align-items:baseline;gap:.4rem}
.sem-det summary::-webkit-details-marker{display:none}
.sem-det summary::before{content:"\203A ";color:var(--brand2);font-weight:800}
.sem-det[open] summary::before{content:"\2304 "}
.sem-det-box{width:19rem;max-width:100%;margin:.35rem 0 .1rem;padding:.5rem .6rem;
  background:#f8fafc;border:1px solid var(--line);border-radius:8px;
  font-size:.7rem;line-height:1.55;white-space:normal;color:var(--ink)}
.sem-det-box p{margin:.25rem 0}
.sem-det-box .sem-det-t{font-size:.65rem;font-weight:800;letter-spacing:.04em;
  text-transform:uppercase;color:var(--mut);margin:.5rem 0 .1rem}
.sem-det-box ul{margin:.1rem 0 .2rem;padding-left:1rem}
.sem-det-box li{margin:.1rem 0}
.sem-det-box li .pill{font-size:.6rem;padding:.05rem .4rem}
.sem-det-box a{font-weight:700}
.sem-empty{padding:.7rem .8rem;white-space:normal}
