/* =========================================================
   Layouts especificos de cada uno de los 7 dashboards
   ========================================================= */

/* ---------- Dashboard 0 — Executive (Project Controls) ----------
   Rediseño 2026-08-03: dashboard ejecutivo de Project Controls centrado en
   CAPEX > Procurement > Milestones. Se retiraron Ingeniería y Cambios de
   Diseño (RE) por pedido del usuario. Paleta ejecutiva desaturada
   (Charts.PALETTE.exec) en vez de la paleta de series saturada.
   Filas: timeline · KPIs · CAPEX+Procurement · Hitos+Licitaciones          */
/* 12 columnas para poder darle a CAPEX media pantalla en alto completo
   (2 filas) y repartir el resto sin que ninguna tarjeta quede angosta.
   ALTURAS: el slide es fijo (1600x900) y no hay scroll, asi que cada alto
   esta calculado contra el contenido real. Al tocar cualquiera de estos
   valores hay que re-verificar que ninguna tarjeta desborde. */
#dash-0 .dash-body {
  grid-template-columns: repeat(12, 1fr);
  /* fila 1 = 138px (antes 92): el roadmap pasa a dos pistas, fases arriba del
     eje y edificios abajo. Los 46px extra salen de las filas 3/4. */
  grid-template-rows: 132px 104px 1fr 1fr 30px;
  gap: 10px;
}
/* 2026-08-05: el Schedule pasa a ocupar la media pantalla de alto completo que
   tenia CAPEX, y CAPEX baja al bloque que ocupaban Key Milestones (retirada por
   redundar con el roadmap de arriba) y Facility Area (que tiene su propia
   seccion 2). */
#dash-0 .ex-timeline { grid-column: 1 / -1;  grid-row: 1; }
/* SCM baja a media columna y la curva S ocupa la otra mitad. */
#dash-0 .ex-status   { grid-column: 1 / -1;  grid-row: 2; }
#dash-0 .ex-schedule { grid-column: 1 / 7;   grid-row: 3 / 5; }  /* priority 1: full height */
#dash-0 .ex-scm      { grid-column: 7 / 10;  grid-row: 3; }
#dash-0 .ex-curva    { grid-column: 10 / 13; grid-row: 3; }
#dash-0 .ex-capex    { grid-column: 7 / 10;  grid-row: 4; }
#dash-0 .ex-areas    { grid-column: 10 / 13; grid-row: 4; }
#dash-0 .ex-compl    { grid-column: 1 / -1;  grid-row: 5; }
#dash-0 .ex-schedule .legend-row { font-size: 10px; gap: 10px; margin-bottom: 6px; }
#dash-0 .ex-schedule .sch-convention { font-size: 10px; }

/* Chart container: a <canvas> carries intrinsic 300x150, so a flex:1 box
   without min-height:0 never shrinks below 150px and the card overflows.
   Taking the canvas out of flow lets the box report the real space, which is
   what mountChart reads. */
#dash-0 .chart-box { flex: 1; min-height: 0; position: relative; overflow: hidden; }
#dash-0 .chart-box > canvas { position: absolute; top: 0; left: 0; }
#dash-0 .ar-foot { font-size: 10px; color: var(--gray-600); margin-top: 5px; padding-top: 5px; border-top: 1px solid var(--gray-100); }
#dash-0 .ar-foot b { color: var(--navy-800); }

/* Mandatory exchange-rate label next to any monetary block. */
#dash-0 .fx-note { font-size: 9.5px; color: var(--gray-600); margin-top: 5px; font-weight: 700; letter-spacing: 0.01em; }

/* ---- Franja de indicadores complementarios (peso visual bajo a proposito) ---- */
#dash-0 .ex-compl {
  display: flex; align-items: center; gap: 22px;
  background: var(--white); border: 1px solid var(--hair); border-radius: var(--radius);
  box-shadow: var(--shadow-card); padding: 0 16px;
}
#dash-0 .ex-compl .tit {
  font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--gray-400); flex: 0 0 auto;
}
#dash-0 .ex-compl .it { font-size: 11px; color: var(--gray-600); white-space: nowrap; }
#dash-0 .ex-compl .it b { color: var(--navy-800); font-variant-numeric: tabular-nums; }
#dash-0 .ex-compl .grow { flex: 1; }

#dash-0 .card h3 { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }

/* ---- KPI ejecutivo ---- */
#dash-0 .ex-kpi {
  background: var(--white); border-radius: var(--radius); box-shadow: var(--shadow-card);
  border: 1px solid var(--hair); padding: 7px 12px;
  display: flex; flex-direction: column; justify-content: center;
  position: relative; overflow: hidden;
}
#dash-0 .ex-kpi::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: #0A0A0A; }
#dash-0 .ex-kpi.ok::before   { background: #4A6B52; }
#dash-0 .ex-kpi.warn::before { background: #7C6548; }
#dash-0 .ex-kpi.crit::before { background: #8C3A2E; }
#dash-0 .ex-kpi.na::before   { background: #9AA1A7; }
#dash-0 .ex-kpi .l {
  font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--gray-600); line-height: 1.2; display: flex; align-items: center; gap: 4px;
}
#dash-0 .ex-kpi .v {
  font-family: var(--font-serif); font-size: 27px; font-weight: 700;
  color: #0A0A0A; line-height: 1.1; margin-top: 2px; font-variant-numeric: tabular-nums;
}
#dash-0 .ex-kpi.ok .v   { color: #4A6B52; }
#dash-0 .ex-kpi.warn .v { color: #7C6548; }
#dash-0 .ex-kpi.crit .v { color: #8C3A2E; }
#dash-0 .ex-kpi.na .v   { color: #9AA1A7; font-size: 17px; }
#dash-0 .ex-kpi .s { font-size: 10px; color: var(--gray-600); margin-top: 1px; line-height: 1.25; }

/* ---- Timeline ejecutivo de hitos ---- */
#dash-0 .ex-timeline { padding: 7px 20px 5px 20px; justify-content: flex-start; }
#dash-0 .tl-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1px; flex: 0 0 auto; }
#dash-0 .tl-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--navy-800); }
#dash-0 .tl-basis { font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--gray-600); font-size: 10px; }
#dash-0 .tl-corte {
  font-size: 10px; font-weight: 700; color: #0A0A0A;
  background: var(--gray-050); border: 1px solid var(--gray-200);
  border-radius: 100px; padding: 2px 10px;
}
#dash-0 .tl-wrap { position: relative; flex: 1; min-height: 0; margin: 0 8px; }
#dash-0 .tl-axis { position: absolute; left: 0; right: 0; top: 34px; height: 3px; background: #DDE0E2; border-radius: 2px; }
/* Tramo recorrido del eje en gris azulado corporativo, no en verde. */
#dash-0 .tl-axis-done { position: absolute; left: 0; top: 34px; height: 3px; background: #788189; border-radius: 2px; }
#dash-0 .tl-hito { position: absolute; top: 0; transform: translateX(-50%); text-align: center; width: 128px; }
#dash-0 .tl-hito .lbl {
  font-size: 10px; font-weight: 700; color: var(--navy-800); line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#dash-0 .tl-hito .fch { font-size: 9.5px; color: var(--gray-600); line-height: 1.2; margin-bottom: 3px; }
#dash-0 .tl-hito .pt {
  width: 13px; height: 13px; border-radius: 50%; margin: 0 auto;
  border: 2.5px solid var(--white); box-shadow: 0 0 0 1.5px #BBC0C4;
  background: #BBC0C4; position: relative; top: 1px;
}
#dash-0 .tl-hito.done .pt { background: #4A6B52; box-shadow: 0 0 0 1.5px #4A6B52; }
#dash-0 .tl-hito.curso .pt { background: #7C6548; box-shadow: 0 0 0 1.5px #7C6548; }
#dash-0 .tl-hito.late .pt { background: #8C3A2E; box-shadow: 0 0 0 1.5px #8C3A2E; }
/* ---- pista inferior del roadmap: edificios de Fase / 2 / 3 ----
   Van bajo el eje para que un edificio que cierra el MISMO dia que su fase no
   quede tapado por ella. Tipografia un paso mas ligera que las fases: la
   jerarquia se lee sola sin necesidad de leyenda. */
#dash-0 .tl-edif { position: absolute; top: 44px; transform: translateX(-50%); text-align: center; width: 108px; }
#dash-0 .tl-edif .pt {
  width: 10px; height: 10px; border-radius: 50%; margin: 0 auto 4px auto;
  background: #fff; border: 2px solid #788189; box-sizing: border-box;
}
#dash-0 .tl-edif.done .pt { background: #4A6B52; border-color: #4A6B52; }
#dash-0 .tl-edif.curso .pt { background: #7C6548; border-color: #7C6548; }
#dash-0 .tl-edif.late .pt { background: #8C3A2E; border-color: #8C3A2E; }
#dash-0 .tl-edif .lbl {
  font-size: 9px; font-weight: 600; color: var(--gray-600); line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#dash-0 .tl-edif .fch { font-size: 8.5px; color: var(--gray-400); line-height: 1.2; }

#dash-0 .tl-hoy-ln { position: absolute; top: 26px; height: 16px; width: 2px; margin-left: -1px; background: #8C3A2E; }
#dash-0 .tl-hoy { position: absolute; top: 43px; white-space: nowrap; }
#dash-0 .tl-hoy .tag {
  font-size: 9.5px; font-weight: 700; color: #8C3A2E; white-space: nowrap;
  border: 1px solid #8C3A2E; border-radius: 4px; padding: 1px 6px; background: var(--white);
}

/* ---- CAPEX ----
   La tarjeta ocupa media columna (3 de 12) desde que Facility Area volvio a la
   fila 4, asi que el bloque de cifras se apila en vez de ir en linea y queda una
   sola grafica, a la que se le da todo el alto restante. */
/* Estos margenes estan medidos: con 5/7px la novena categoria se cortaba por
   4px al fondo de la tarjeta. */
#dash-0 .cap-big { margin-bottom: 2px; }
#dash-0 .cap-big .v { font-family: var(--font-serif); font-size: 22px; font-weight: 700; color: #0A0A0A; line-height: 1; }
#dash-0 .cap-big .l { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--gray-600); }
#dash-0 .cap-sec { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-bottom: 4px; }
#dash-0 .cap-sec .v { font-size: 12px; font-weight: 700; color: #56626C; line-height: 1.15; font-variant-numeric: tabular-nums; white-space: nowrap; }
#dash-0 .cap-sec .l { font-size: 8.5px; color: var(--gray-600); text-transform: uppercase; letter-spacing: 0.03em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Categorias como lista de barras en HTML en vez de grafica Chart.js: en media
   columna la grafica quedaba a ~13px por barra con las etiquetas montadas.
   Aqui el alto de fila es controlable y las 9 categorias se reparten el espacio
   con space-evenly, sin encimarse. */
#dash-0 .cap-cats { flex: 1; min-height: 0; display: flex; flex-direction: column; justify-content: space-evenly; overflow: hidden; }
#dash-0 .cap-cat { display: flex; align-items: center; gap: 6px; }
/* 152px: es lo que mide "Activo de mayor nombre", el rubro mas largo
   del catalogo. Con menos se recortaba justo ese. */
#dash-0 .cap-cat .n {
  flex: 0 0 148px; font-size: 9px; line-height: 1.1; color: var(--gray-600);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#dash-0 .cap-cat .bar { flex: 1; height: 7px; background: var(--gray-050); border-radius: 2px; min-width: 0; overflow: hidden; }
#dash-0 .cap-cat .bar i { display: block; height: 100%; border-radius: 2px; }
#dash-0 .cap-cat .v { flex: 0 0 56px; text-align: right; font-size: 9px; line-height: 1.1; font-weight: 700; color: var(--navy-800); font-variant-numeric: tabular-nums; }
#dash-0 .cap-sub {
  font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--gray-600); margin-bottom: 3px; line-height: 1.25;
}
#dash-0 .cap-sub .n { font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--gray-400); }
#dash-0 .cap-ejec {
  margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--gray-100);
  display: flex; align-items: center; gap: 10px; flex: 0 0 auto;
}
#dash-0 .cap-ejec .bloque { flex: 1; display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
#dash-0 .cap-ejec .celda {
  background: var(--gray-050); border: 1px dashed #BBC0C4; border-radius: 4px;
  padding: 2px 6px; text-align: center;
}
#dash-0 .cap-ejec .celda .v { font-size: 12px; font-weight: 700; color: #9AA1A7; line-height: 1.25; }
#dash-0 .cap-ejec .celda .l { font-size: 8px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--gray-600); line-height: 1.2; white-space: nowrap; }
#dash-0 .cap-ejec .msg { flex: 0 0 210px; font-size: 9px; color: var(--gray-600); line-height: 1.3; }
#dash-0 .cap-ejec .msg b { color: #7C6548; }

/* ---- Procurement ---- */
#dash-0 .pr-estados { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; margin-bottom: 9px; }
#dash-0 .pr-estado { border-radius: 6px; padding: 6px 4px; text-align: center; }
#dash-0 .pr-estado .v { font-family: var(--font-serif); font-size: 21px; font-weight: 700; line-height: 1.05; }
#dash-0 .pr-estado .l { font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; line-height: 1.2; margin-top: 1px; }
#dash-0 .pr-estado.adj  { background: #EAEFEB; color: #4A6B52; }
#dash-0 .pr-estado.lic  { background: #F1EDE8; color: #7C6548; }
#dash-0 .pr-estado.pend { background: #F4F4F2; color: #6E6E6E; }
#dash-0 .pr-estado.tot  { background: #F4F4F2; color: #0A0A0A; }
/* 2 columns: all 10 packages fit without scrolling (PNG export does not
   capture scrolled content, and the card has width to spare). */
/* overflow:hidden + interlineado corto: el cronograma vigente trae 11 paquetes
   (6 filas en 2 columnas) y con el espaciado anterior la ultima fila se montaba
   sobre la leyenda de la tarjeta. */
/* ---- SCM: desviacion por paquete ----
   Barra divergente desde una linea de cero: derecha = atraso, izquierda =
   adelanto. Sustituye a la lista de texto, que a este ancho quedaba apretada y
   no comunicaba magnitud. El alto de fila se reparte con space-between para
   que N paquetes llenen la tarjeta sin desbordarla. */
#dash-0 .scm-dev { flex: 1; min-height: 0; display: flex; flex-direction: column; justify-content: space-evenly; overflow: hidden; }
#dash-0 .scm-row { display: flex; align-items: center; gap: 6px; line-height: 1.15; }
/* 140px: en media columna el nombre no puede llevarse casi la mitad del ancho
   o la barra deja de comunicar magnitud. */
#dash-0 .scm-row .n {
  flex: 0 0 140px; font-size: 9.5px; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#dash-0 .scm-row .bar { flex: 1; position: relative; height: 9px; background: var(--gray-050); border-radius: 2px; min-width: 0; }
#dash-0 .scm-row .bar i { position: absolute; top: 0; bottom: 0; border-radius: 2px; display: block; }
#dash-0 .scm-row .bar b { position: absolute; top: -2px; bottom: -2px; width: 1px; background: #BBC0C4; }
#dash-0 .scm-row .v { flex: 0 0 42px; text-align: right; font-size: 10px; font-weight: 700; font-variant-numeric: tabular-nums; }
#dash-0 .scm-row .d { flex: 0 0 44px; text-align: right; font-size: 9px; color: var(--gray-600); font-variant-numeric: tabular-nums; }

/* Tender checklist progress, merged in from the former "Procurement Status"
   card so both procurement views live in a single visualization. */
#dash-0 .pr-prog { flex: 0 0 92px; display: flex; align-items: center; gap: 5px; }
#dash-0 .pr-prog .pr-bar { flex: 1; height: 8px; border-radius: 2px; background: #F4F4F2; overflow: hidden; display: flex; }
#dash-0 .pr-prog .pr-bar i { display: block; height: 100%; }
#dash-0 .pr-prog .pr-num { font-size: 9px; color: var(--gray-600); font-variant-numeric: tabular-nums; white-space: nowrap; }
#dash-0 .pr-prog-empty { font-size: 8.5px; color: var(--gray-400); font-style: italic; text-align: right; }
#dash-0 .pr-leyenda { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--gray-100); display: flex; gap: 14px; flex-wrap: wrap; font-size: 9.5px; color: var(--gray-600); flex: 0 0 auto; }
#dash-0 .pr-leyenda .it { display: flex; align-items: center; gap: 4px; }
#dash-0 .pr-leyenda .sw { width: 10px; height: 10px; border-radius: 2px; }

/* ---- Hitos (detalle) ---- */
#dash-0 .hi-tabla { flex: 1; min-height: 0; overflow-y: auto; }
#dash-0 .hi-row { display: flex; align-items: center; gap: 9px; padding: 5px 0; border-bottom: 1px solid var(--gray-050); }
#dash-0 .hi-row .est { flex: 0 0 9px; height: 9px; border-radius: 50%; }
#dash-0 .hi-row .est.done  { background: #4A6B52; }
#dash-0 .hi-row .est.curso { background: #7C6548; }
#dash-0 .hi-row .est.late  { background: #8C3A2E; }
#dash-0 .hi-row .est.next  { background: #BBC0C4; }
#dash-0 .hi-row .n { flex: 1; font-size: 11.5px; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#dash-0 .hi-row .f { flex: 0 0 auto; font-size: 11px; font-variant-numeric: tabular-nums; color: var(--gray-600); }
#dash-0 .hi-row .d { flex: 0 0 86px; text-align: right; font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums; }

/* ---------- Dashboard 1 — RFP Budget / CAPEX ---------- */
/* Solo 4 tarjetas (antes 6): la dona de participacion repetia el % de la tabla
   y la composicion por categoria le quitaba el alto que necesitaban las
   graficas principales, que quedaban en ~11px por barra con las etiquetas
   montadas. Alturas verificadas contra el contenido real; no reducir sin
   volver a medir. */
#dash-1 .dash-body {
  grid-template-columns: repeat(7, 1fr);
  grid-template-rows: 26px 98px 1fr 1fr;
}
#dash-1 .controles { grid-column: 1 / -1; grid-row: 1; display: flex; justify-content: flex-end; align-items: center; }
#dash-1 .kpi-row { grid-column: 1 / -1; grid-row: 2; display: grid; grid-template-columns: repeat(6, 1fr); gap: 11px; }

#dash-1 .apr-resumen     { grid-column: 1 / 5; grid-row: 3; }
#dash-1 .apr-comparacion { grid-column: 5 / 8; grid-row: 3; }
/* The by-building chart absorbed the former "Building Detail" table, so it
   now spans the full width instead of sharing the row. */
#dash-1 .cx-bar          { grid-column: 1 / 8; grid-row: 4; }
#dash-1 .cx-bar-foot { font-size: 10px; color: var(--gray-600); margin-top: 5px; padding-top: 5px; border-top: 1px solid var(--gray-100); }
#dash-1 .cx-bar-foot b { color: var(--navy-800); }
#dash-1 .fx-note { font-size: 9.5px; color: var(--gray-600); margin-top: 5px; font-weight: 700; }

/* Contenedor de grafica: el <canvas> trae 300x150 intrinsecos, asi que un
   contenedor flex:1 sin min-height:0 nunca baja de 150px y la tarjeta se
   desborda. Sacando el canvas del flujo (absolute) el contenedor mide solo
   el espacio realmente disponible, que es lo que mountChart necesita leer. */
#dash-1 .chart-box { flex: 1; min-height: 0; position: relative; overflow: hidden; }
#dash-1 .chart-box > canvas { position: absolute; top: 0; left: 0; }

/* toggle de moneda COP/USD */
.moneda-toggle { display: inline-flex; border: 1px solid var(--gray-200); border-radius: 7px; overflow: hidden; }
.moneda-toggle button {
  font-family: var(--font-sans); font-size: 11.5px; font-weight: 700; color: var(--navy-700);
  background: var(--white); border: none; padding: 5px 12px; cursor: pointer;
}
.moneda-toggle button.activo { background: var(--navy-700); color: var(--white); }
.moneda-toggle button + button { border-left: 1px solid var(--gray-200); }

/* CAPEX Aprobado: card principal */
#dash-1 .apr-resumen .apr-head { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 6px; }
#dash-1 .apr-total { font-family: var(--font-serif); font-size: 34px; font-weight: 700; color: var(--navy-800); line-height: 1.1; }
#dash-1 .apr-total-label { font-size: 11px; color: var(--gray-600); text-transform: uppercase; letter-spacing: 0.02em; font-weight: 700; }
#dash-1 .apr-desglose { display: flex; gap: 16px; margin: 6px 0 8px 0; font-size: 11.5px; color: var(--gray-600); }
#dash-1 .apr-desglose b { color: var(--navy-800); }
#dash-1 .apr-tasa-nota { font-size: 10.5px; color: var(--amber-warn); margin-top: 6px; }

/* Comparacion Aprobado vs RFP */
#dash-1 .apr-comp-bars { margin: 6px 0 4px 0; }
#dash-1 .apr-comp-row { margin-bottom: 7px; }
#dash-1 .apr-comp-label { display: flex; justify-content: space-between; font-size: 11.5px; margin-bottom: 2px; }
#dash-1 .apr-comp-label b { color: var(--navy-800); }
#dash-1 .apr-comp-track { height: 13px; background: var(--gray-100); border-radius: 4px; overflow: hidden; }
#dash-1 .apr-comp-fill { height: 100%; border-radius: 4px; }
/* % destacado en una linea propia (antes era un .kpi completo que no cabia
   en la tarjeta y se recortaba a la mitad). */
#dash-1 .apr-pct { display: flex; align-items: baseline; gap: 8px; margin-top: 2px; }
#dash-1 .apr-pct .v { font-family: var(--font-serif); font-size: 26px; font-weight: 700; color: #0A0A0A; line-height: 1; }
#dash-1 .apr-pct .l { font-size: 11px; color: var(--gray-600); }
#dash-1 .apr-equivalencias { margin-top: 8px; padding-top: 7px; border-top: 1px solid var(--gray-100); }
#dash-1 .apr-eq-row { display: flex; align-items: center; gap: 8px; font-size: 11px; padding: 2px 0; }
/* 172px: lo que mide "Activo de mayor nombre", el rubro mas largo */
#dash-1 .apr-eq-row .n { flex: 0 0 172px; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#dash-1 .apr-eq-row .pb { flex: 1; height: 7px; background: var(--gray-100); border-radius: 2px; min-width: 0; overflow: hidden; }
#dash-1 .apr-eq-row .pb i { display: block; height: 100%; background: #0A0A0A; border-radius: 2px; }
#dash-1 .apr-eq-row .p { flex: 0 0 34px; text-align: right; font-weight: 700; color: #0A0A0A; font-variant-numeric: tabular-nums; }
#dash-1 .apr-eq-row .v { flex: 0 0 auto; font-variant-numeric: tabular-nums; color: var(--gray-600); white-space: nowrap; }

/* ---------- Dashboard 2 — Areas ---------- */
#dash-2 .dash-body {
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: 100px 1fr 1fr;
}
#dash-2 .kpi-row { grid-column: 1 / -1; grid-row: 1; display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
#dash-2 .ar-chart { grid-column: 1 / 3; grid-row: 2 / 4; }
#dash-2 .chart-box { flex: 1; min-height: 0; position: relative; overflow: hidden; }
#dash-2 .chart-box > canvas { position: absolute; top: 0; left: 0; }
#dash-2 .ar-detalle-a { grid-column: 3; grid-row: 2; }
#dash-2 .ar-detalle-b { grid-column: 3; grid-row: 3; }

/* ---------- Dashboard 3 — RIP ---------- */
#dash-3 .dash-body {
  grid-template-columns: repeat(7, 1fr);
  grid-template-rows: auto 98px 1fr; /* 98: el .kpi mide 93 de contenido, 92 lo recortaba */
}
#dash-3 .filters-bar { grid-column: 1 / -1; grid-row: 1; }
#dash-3 .kpi-row { grid-column: 1 / -1; grid-row: 2; display: grid; grid-template-columns: repeat(6, 1fr); gap: 11px; }
#dash-3 .rip-matriz { grid-column: 1 / 3; grid-row: 3; }
#dash-3 .rip-tabla { grid-column: 3 / 8; grid-row: 3; }
#dash-3 .rfi-foot { font-size: 10.5px; color: var(--gray-600); margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--gray-100); flex: 0 0 auto; }
#dash-3 .rfi-foot b { color: var(--navy-800); }

/* ---------- Barra de filtros (reutilizable) ---------- */
.filters-bar {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 14px;
  background: var(--white);
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 10px 16px;
}
.filter-item { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.filter-item label {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--navy-800);
}
.filter-item select {
  font-family: var(--font-sans); font-size: 12.5px; color: var(--ink);
  border: 1px solid var(--gray-200); border-radius: 6px; padding: 6px 8px;
  background: var(--white); cursor: pointer;
}
.filter-item select:focus { outline: 2px solid var(--blue-accent); outline-offset: 1px; }

/* 38px (no 20px) en la columna de rotulos: los ejes pasaron de digitos 1-5 a
   palabras (Bajo/Medio/Alto) y "Medio" no cabia en 20px. */
#dash-3 .rip-grid-wrap {
  flex: 1; min-height: 0;
  display: grid;
  grid-template-columns: 38px 1fr;
  grid-template-rows: 1fr 18px;
  gap: 4px;
}
#dash-3 .rip-ticks-y {
  grid-column: 1; grid-row: 1;
  display: flex; flex-direction: column;
}
#dash-3 .rip-ticks-x {
  grid-column: 2; grid-row: 2;
  display: flex; flex-direction: row;
}
#dash-3 .rip-ticks-y span, #dash-3 .rip-ticks-x span {
  flex: 1; display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: var(--gray-400);
}
#dash-3 .rip-corner { grid-column: 1; grid-row: 2; }
#dash-3 .rip-grid {
  grid-column: 2; grid-row: 1;
  display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); gap: 4px;
}
#dash-3 .rip-celda {
  border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700;
}
#dash-3 .rip-celda.green { background: #EAEFEB; color: #4A6B52; }
#dash-3 .rip-celda.amber { background: #F1EDE8; color: #B0A290; }
#dash-3 .rip-celda.red { background: #F4E9E7; color: #8C3A2E; }
#dash-3 .rip-celda.con-datos.green { background: var(--green-ok); color: #fff; }
#dash-3 .rip-celda.con-datos.amber { background: var(--amber-warn); color: #fff; }
#dash-3 .rip-celda.con-datos.red { background: var(--alert); color: #fff; }
#dash-3 .rip-celda .n { font-size: 17px; }
#dash-3 .rip-celda .s { opacity: 0.7; font-weight: 400; }

/* ---------- Dashboard 4 — Ingenieria ---------- */
/* etiquetas de disciplina: se ajustan en varias lineas en vez de truncarse */
#dash-4 .disc-wrap { display: flex; flex-wrap: wrap; gap: 4px; justify-content: center; }
#dash-4 .disc-chip {
  display: inline-block;
  background: var(--white);
  border: 1px solid #CBC1B4;
  color: #7C6548;
  font-size: 10.5px; font-weight: 600;
  padding: 2px 7px; border-radius: 100px;
  white-space: nowrap;
}
#dash-4 .dash-body {
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: 100px 1fr;
}
#dash-4 .kpi-row { grid-column: 1 / -1; grid-row: 1; display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
#dash-4 .ing-heatmap { grid-column: 1 / 3; grid-row: 2; }
#dash-4 .ing-barras { grid-column: 3; grid-row: 2; }

/* ---------- Dashboard 5 — Procurement Status ---------- */
/* Fila 3 pasa de la tabla plegable (que salia colapsada y dejaba ~280px en
   blanco) al Gantt de licitacion con selector de paquete. El tracker se
   comprime de 288 a 250px para darle ese aire al Gantt. */
#dash-5 .dash-body {
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: 96px 250px 1fr;
}
#dash-5 .kpi-row { grid-column: 1 / -1; grid-row: 1; display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
#dash-5 .pg-card  { grid-column: 1 / -1; grid-row: 2; }
#dash-5 .bid-tabla, #dash-5 .bid-gantt { grid-column: 1 / -1; grid-row: 3; }
#dash-5 .kpi .value { font-size: 26px; }
#dash-5 .kpi .sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- Phase-gate tracker (replaces the traffic-light activity strip) ----
   One row per package, one column per lifecycle stage. State is carried by
   fill weight within the corporate blue ramp, not by a red/amber/green code. */
#dash-5 .pg-grid { flex: 1; min-height: 0; display: flex; flex-direction: column; justify-content: space-evenly; }
#dash-5 .pg-row { display: flex; align-items: center; }
#dash-5 .pg-name {
  flex: 0 0 172px; display: flex; flex-direction: column; gap: 1px; padding-right: 10px;
  overflow: hidden;
}
#dash-5 .pg-name b { font-size: 12px; color: var(--navy-800); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#dash-5 .pg-name span { font-size: 9.5px; color: var(--gray-600); font-variant-numeric: tabular-nums; }
#dash-5 .pg-cell { flex: 1; position: relative; display: flex; align-items: center; justify-content: center; height: 34px; min-width: 0; }
#dash-5 .pg-current {
  flex: 0 0 132px; padding-left: 12px; display: flex; flex-direction: column; gap: 1px;
  border-left: 1px solid var(--gray-100); overflow: hidden;
}
#dash-5 .pg-current b { font-size: 11px; color: var(--navy-800); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#dash-5 .pg-current span { font-size: 9.5px; color: var(--gray-600); }

/* connector between stage markers */
#dash-5 .pg-line { position: absolute; top: 50%; left: 0; right: 0; height: 2px; background: var(--gray-200); transform: translateY(-50%); }
#dash-5 .pg-line.first { left: 50%; }
#dash-5 .pg-line.last { right: 50%; }

#dash-5 .mk {
  position: relative; z-index: 1;
  width: 15px; height: 15px; border-radius: 50%;
  background: #F4F4F2; border: 2px solid #DDE0E2; box-sizing: border-box;
}
#dash-5 .mk.complete { background: #0A0A0A; border-color: #0A0A0A; }
#dash-5 .mk.progress { background: #fff; border-color: #0A0A0A; border-width: 4px; }
#dash-5 .mk.pending  { background: #F4F4F2; border-color: #BBC0C4; }
#dash-5 .mk.unknown  { background: repeating-linear-gradient(45deg, #fff, #fff 2px, #DDE0E2 2px, #DDE0E2 4px); border-color: #DDE0E2; }

/* header row with stage names */
#dash-5 .pg-head .pg-cell { height: auto; align-items: flex-end; padding-bottom: 3px; }
#dash-5 .pg-stage-lbl {
  font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em;
  color: var(--gray-600); text-align: center; line-height: 1.2; padding: 0 2px;
}
#dash-5 .pg-head .pg-current { font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; color: var(--gray-600); border-left: none; }

#dash-5 .pg-legend {
  margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--gray-100);
  display: flex; gap: 18px; flex-wrap: wrap; font-size: 10px; color: var(--gray-600); flex: 0 0 auto;
}
#dash-5 .pg-legend .it { display: flex; align-items: center; gap: 6px; }

/* Schedule Variance colouring (Procurement Schedule table). Uses the sober
   executive red/green, not the saturated brand red, so it stays consistent
   with the rest of the corporate styling. */
#dash-5 .var-behind { color: #8C3A2E; font-variant-numeric: tabular-nums; }
#dash-5 .var-ahead  { color: #4A6B52; font-variant-numeric: tabular-nums; }
#dash-5 .var-behind-lbl { font-size: 11px; color: #8C3A2E; opacity: 0.85; }
#dash-5 .var-ahead-lbl  { font-size: 11px; color: #4A6B52; opacity: 0.85; }

#dash-5 .bid-tabla-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 9px; }
#dash-5 .bid-toggle-btn {
  font-family: var(--font-sans); font-size: 12px; font-weight: 700; color: var(--navy-700);
  background: var(--gray-050); border: 1px solid var(--gray-200); border-radius: 6px;
  padding: 6px 11px; cursor: pointer; white-space: nowrap;
}
#dash-5 .bid-toggle-btn:hover { background: var(--gray-100); }

/* ---------- Gantt Baseline vs Current Forecast (secciones 4 y 5) ----------
   Lo dibuja js/gantt.js y lo comparten el cronograma ejecutivo (seccion 5) y el
   cronograma de licitacion por paquete (seccion 4). Los anchos de columna y la
   altura de fila llegan como custom properties desde el JS: cambian segun la
   seccion y, en Procurement, segun el paquete seleccionado. */
.sch-card { overflow: hidden; }
.sch-card h3 { display: flex; align-items: baseline; gap: 8px; }
.sch-card h3 .grow { flex: 1; }
.sch-convention { font-size: 11px; text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--gray-600); white-space: nowrap; }
.sch-convention b { color: var(--navy-800); }
.sch-card .legend-row { margin-bottom: 8px; }
.sch-legend-note { font-size: 11px; color: var(--gray-400); font-style: italic; }
.legend-dataline {
  display: inline-block; width: 0; height: 13px;
  border-left: 2px dashed var(--alert); margin: 0 6px 0 4px;
}

/* selector de paquete (seccion 4) */
.sch-picker { display: flex; gap: 4px; flex: 0 0 auto; }
.sch-pick-btn {
  font-family: var(--font-sans); font-size: 11px; font-weight: 700;
  text-transform: none; letter-spacing: 0;
  color: var(--navy-700); background: var(--gray-050);
  border: 1px solid var(--gray-200); border-radius: 6px;
  padding: 4px 10px; cursor: pointer; white-space: nowrap;
}
.sch-pick-btn:hover { background: var(--gray-100); }
.sch-pick-btn.on { background: var(--navy-700); border-color: var(--navy-700); color: var(--white); }

.sch-host { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.sch-grid { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }

/* Fila generica: [nombre][pista elastica][baseline finish][forecast finish][var].
   El eje y las filas comparten los mismos anchos fijos, y por eso el overlay de
   lineas de mes / Data Date puede posicionarse con esos mismos px y quedar
   alineado al pixel con las barras. */
.sch-axis, .sch-row { display: flex; align-items: stretch; }
.sch-lbl {
  flex: 0 0 var(--sch-label-w, 260px); min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  display: flex; align-items: center;
}
.sch-track { flex: 1; position: relative; min-width: 0; }
.sch-c1, .sch-c2, .sch-var, .sch-dev {
  display: flex; align-items: center; justify-content: flex-end;
  text-align: right; padding-right: 8px;
  font-size: 11.5px; color: var(--gray-600); font-variant-numeric: tabular-nums;
}
.sch-c1 { flex: 0 0 var(--sch-c1-w, 102px); }
.sch-c2 { flex: 0 0 var(--sch-c2-w, 102px); color: var(--navy-800); font-weight: 600; }
.sch-var { flex: 0 0 var(--sch-var-w, 46px); padding-right: 8px; font-weight: 700; }
.sch-dev { flex: 0 0 var(--sch-dev-w, 50px); padding-right: 2px; font-weight: 700; }
.sch-row.is-phase .sch-c1, .sch-row.is-phase .sch-c2 { font-weight: 700; color: var(--navy-900); }

/* ---- eje de dos niveles: anio arriba, trimestre debajo ---- */
.sch-axis { flex: 0 0 auto; }
.sch-axis-year { height: 15px; }
.sch-axis-q { height: 16px; border-bottom: 1px solid var(--gray-400); }
.sch-axis-q .sch-lbl,
.sch-axis-q .sch-c1, .sch-axis-q .sch-c2, .sch-axis-q .sch-var, .sch-axis-q .sch-dev {
  font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--gray-600); padding-left: 6px; white-space: nowrap;
}
.sch-axis-q .sch-c1, .sch-axis-q .sch-c2, .sch-axis-q .sch-var, .sch-axis-q .sch-dev { padding-left: 0; }
.sch-band {
  position: absolute; top: 0; bottom: 0;
  border-left: 1px solid var(--gray-200);
  display: flex; align-items: center; overflow: hidden;
}
.sch-band span { font-size: 10px; color: var(--gray-600); padding-left: 5px; white-space: nowrap; }
.sch-band.is-year { border-left-color: var(--gray-400); }
.sch-band.is-year span { font-size: 11.5px; font-weight: 700; color: var(--navy-800); letter-spacing: 0.04em; }

/* ---- filas del cronograma ---- */
.sch-rows { position: relative; z-index: 1; }
.sch-row {
  height: var(--sch-row-h, 26px); box-sizing: border-box;
  border-bottom: 1px solid var(--gray-100);
}
.sch-row.is-phase {
  border-top: 1.5px solid var(--navy-700);
  border-bottom-color: var(--gray-200);
  background: var(--gray-050);
}
.sch-row .sch-track { height: 100%; }

/* ---- overlays alineados al area de tiempo ----
   left/right en px identicos a los anchos de las columnas fijas: mezclar % con
   px dentro de un calc() sobre un contenedor flex daba desalineacion de ~1px
   entre las lineas de mes y las barras. */
.sch-plot {
  position: absolute; left: var(--sch-label-w, 260px); right: var(--sch-right-w, 250px); top: 0; bottom: 0;
  pointer-events: none; z-index: 0;
}
.sch-plot-top { z-index: 4; }
/* 31px = alto del eje (15 + 16): las lineas de mes empiezan bajo el eje */
.sch-glines { position: absolute; left: 0; right: 0; top: 31px; bottom: 0; }
.sch-gline { position: absolute; top: 0; bottom: 0; border-left: 1px solid var(--gray-100); }
.sch-gline.is-q { border-left-color: var(--gray-200); }
.sch-dataline {
  position: absolute; top: 15px; bottom: 0;
  border-left: 2px dashed var(--alert);
}
.sch-datalbl {
  position: absolute; top: 0; height: 15px; line-height: 15px;
  transform: translateX(-50%);
  font-size: 10px; font-weight: 700; letter-spacing: 0.03em; white-space: nowrap;
  color: var(--alert); background: var(--white);
  padding: 0 5px; border-radius: 2px;
}
.sch-foot { margin-top: 7px; flex: 0 0 auto; }

/* ---------- Dashboard 6 — Schedule ----------
   Un solo Gantt a todo el ancho, 23 filas x 26px = 598px + 31px de eje. */
#dash-6 .dash-body { grid-template-columns: 1fr; grid-template-rows: 1fr; }


/* ---------- Panel de estado del ejecutivo ----------
   Lectura clasica de project controls: costo a la izquierda, avance acumulado
   en la dona central y desempenio de cronograma a la derecha. Inspirado en el
   panel de Cost Controls / Schedule Status que usa el proyecto, con los datos
   que si existen — no hay CPI porque no hay costo ejecutado cargado. */
#dash-0 .ex-status { flex-direction: row; align-items: center; gap: 18px; padding: 8px 16px; }
#dash-0 .st-side { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; }
#dash-0 .st-tit {
  font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--gray-400); margin-bottom: 4px;
}
#dash-0 .st-cost .st-tit { color: #0A0A0A; }
#dash-0 .st-sched .st-tit { color: #4A6B52; }
#dash-0 .st-row { display: flex; gap: 14px; }
#dash-0 .st-m { flex: 1; min-width: 0; }
#dash-0 .st-m .l {
  font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--gray-600); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#dash-0 .st-m .v {
  font-family: var(--font-serif); font-size: 20px; font-weight: 700; line-height: 1.1;
  color: #0A0A0A; font-variant-numeric: tabular-nums; white-space: nowrap;
}
#dash-0 .st-m .s { font-size: 8.5px; color: var(--gray-400); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#dash-0 .st-donut { flex: 0 0 auto; text-align: center; padding: 0 6px; border-left: 1px solid var(--gray-100); border-right: 1px solid var(--gray-100); }
#dash-0 .st-donut svg { display: block; margin: 0 auto; }
#dash-0 .st-donut-l {
  font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--gray-600); margin-top: 1px;
}

/* ---------- Curva S ---------- */
.cs-plot { flex: 1; min-height: 0; position: relative; }
.cs-plot .cs-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.cs-sw { display: inline-block; width: 14px; height: 0; border-top: 2.5px solid; margin-right: 5px; vertical-align: middle; }
.cs-sw.plan { border-color: #0A0A0A; border-top-style: dashed; }
.cs-sw.real { border-color: #4A6B52; }
.cs-sw.corte { border-color: #8C3A2E; border-top-style: dashed; }
.cs-leyenda { margin-bottom: 6px; }
#dash-0 .ex-curva .cs-foot {
  display: flex; gap: 12px; align-items: center; font-size: 9.5px; color: var(--gray-600);
  margin-top: 5px; padding-top: 5px; border-top: 1px solid var(--gray-100);
}
#dash-0 .ex-curva .cs-spi { margin-left: auto; font-weight: 700; color: #7C6548; }
#dash-0 .ex-curva .cs-sw { width: 12px; }

/* ---------- Dashboard 7 — S-Curve ---------- */
#dash-7 .dash-body { grid-template-columns: repeat(4, 1fr); grid-template-rows: 96px 1fr 1fr; }
#dash-7 .kpi-row { grid-column: 1 / -1; grid-row: 1; display: grid; gap: 12px; }
#dash-7 .cs-card { grid-column: 1 / 4; grid-row: 2 / 4; }
#dash-7 .cs-tabla { grid-column: 4; grid-row: 2 / 4; }
#dash-7 .cs-card h3 { display: flex; align-items: center; gap: 8px; }
#dash-7 .cs-card h3 .grow { flex: 1; }
#dash-7 .cs-dona-wrap { flex: 0 0 auto; }
#dash-7 .cs-futuro td { color: var(--gray-400); }
#dash-7 .cs-tabla .table-scroll { flex: 1; min-height: 0; }
