/* ==========================================================================
   CertiProf OS · Estilos por módulo
   ========================================================================== */

/* ====================================================== FICHAJE / RELOJ = */
.punch-hero {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s6); align-items: center;
  padding: var(--s6) var(--s7);
}
@media (max-width: 860px) { .punch-hero { grid-template-columns: minmax(0, 1fr); } }

.clock {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 6vw, 3.6rem); font-weight: 600;
  letter-spacing: -.035em; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.clock .sec { font-size: .5em; color: var(--ink-3); font-weight: 500; margin-left: 2px; }
.punch-state { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s3); }
.punch-actions { display: flex; gap: var(--s3); flex-wrap: wrap; }

.punch-track {
  display: flex; align-items: stretch; gap: 2px;
  height: 38px; margin-top: var(--s5);
  border-radius: var(--r-xs); overflow: hidden;
  background: var(--surface-3);
}
.punch-seg { position: relative; min-width: 2px; }
.punch-seg[data-kind="work"]  { background: var(--c1); }
.punch-seg[data-kind="break"] { background: var(--c3); }
.punch-seg[data-kind="idle"]  { background: var(--surface-3); }
.punch-scale {
  display: flex; justify-content: space-between;
  margin-top: 5px; font-size: var(--fs-2xs); color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}

/* --- Mis horarios (rediseño 31-ago-2026) --- */
.ttl-ico {
  display: inline-grid; place-items: center; width: 30px; height: 30px;
  border-radius: var(--r-sm); background: var(--primary-soft); color: var(--primary);
  vertical-align: middle;
}
.ttl-ico svg { width: 16px; height: 16px; }

.shift-tile {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4) var(--s5); border-radius: var(--r-lg);
}
.shift-tile .sh-ico {
  display: grid; place-items: center; flex: none;
  width: 40px; height: 40px; border-radius: var(--r-sm);
  background: var(--surface);
}
.shift-tile .sh-val {
  font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 700;
  letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
.shift-tile[data-tone="green"]  { background: var(--success-soft); }
.shift-tile[data-tone="green"] .sh-ico { color: var(--success); }
.shift-tile[data-tone="blue"]   { background: var(--info-soft); }
.shift-tile[data-tone="blue"] .sh-ico { color: var(--info); }
.shift-tile[data-tone="purple"] { background: var(--accent-soft); }
.shift-tile[data-tone="purple"] .sh-ico { color: var(--accent); }
.shift-tile[data-tone="orange"] { background: var(--warning-soft); }
.shift-tile[data-tone="orange"] .sh-ico { color: var(--warning); }

.jt-track {
  position: relative; height: 10px; margin-top: var(--s3);
  border-radius: var(--r-full); background: var(--surface-3);
}
.jt-fill { height: 100%; border-radius: var(--r-full); background: var(--c1); }
.jt-thumb {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--c1); border: 3px solid var(--surface);
  box-shadow: var(--shadow-md);
}
.jt-scale {
  position: relative; display: flex; justify-content: space-between;
  margin-top: var(--s2); font-size: var(--fs-xs); color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.jt-now {
  position: absolute; transform: translateX(-50%);
  color: var(--primary); font-weight: 700;
}

.mt-card .mt-ico {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: var(--r-sm);
}
.mt-card .mt-ico svg { width: 17px; height: 17px; }
.mt-card .mt-ico[data-tone="blue"]   { background: var(--info-soft); color: var(--info); }
.mt-card .mt-ico[data-tone="red"]    { background: var(--danger-soft); color: var(--danger); }
.mt-card .mt-ico[data-tone="green"]  { background: var(--success-soft); color: var(--success); }
.mt-card .mt-ico[data-tone="purple"] { background: var(--accent-soft); color: var(--accent); }
.mt-card .mt-val {
  font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 700;
  letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
.mt-bar {
  display: flex; align-items: center; gap: var(--s2); margin-top: var(--s2);
}
.mt-bar .tr {
  flex: 1; height: 7px; border-radius: var(--r-full);
  background: var(--surface-3); overflow: hidden;
}
.mt-bar .tr i {
  display: block; height: 100%; border-radius: var(--r-full);
  background: var(--c1);
}
.mt-bar b { font-size: var(--fs-2xs); color: var(--ink-3); font-weight: 600; }

.wk-list { padding-top: var(--s2); }
.wk-row {
  display: flex; align-items: center; gap: var(--s4);
  padding: var(--s3) var(--s3);
  border-radius: var(--r-md);
}
.wk-row + .wk-row { margin-top: 2px; }
.wk-row.is-today { background: var(--primary-soft); }
.wk-row .wk-ico {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: var(--r-sm);
  background: var(--surface-3); color: var(--ink-3);
}
.wk-row.is-today .wk-ico { background: var(--primary); color: var(--primary-ink); }
.wk-row .wk-ico svg { width: 16px; height: 16px; }
.wk-row .wk-day { flex: 0 0 132px; font-size: var(--fs-sm); font-weight: 700; }
@media (max-width: 640px) { .wk-row .wk-day { flex-basis: 96px; } }

.hist-ok { color: var(--success); display: inline-grid; place-items: center; }

.day-log { display: flex; flex-direction: column; }
.day-log-row {
  display: grid; grid-template-columns: 34px 1fr auto; gap: var(--s3); align-items: center;
  padding: var(--s3) 0; border-bottom: 1px solid var(--border-soft);
}
.day-log-row:last-child { border-bottom: 0; }
.day-log-row .ic {
  display: grid; place-items: center; width: 30px; height: 30px;
  border-radius: var(--r-xs); background: var(--surface-3); color: var(--ink-3);
}
.day-log-row .ic svg { width: 15px; height: 15px; }
.day-log-row .ic[data-k="in"]  { background: var(--success-soft); color: var(--success); }
.day-log-row .ic[data-k="out"] { background: var(--danger-soft); color: var(--danger); }
.day-log-row .ic[data-k="break"] { background: var(--warning-soft); color: var(--warning); }

/* ============================================================== KANBAN = */
/* Las columnas reparten el ancho disponible: en escritorio y tablet el tablero
   entra completo sin desplazamiento lateral. Solo por debajo de 1100px se
   convierte en carrusel horizontal. */
.kanban {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: var(--s3);
  align-items: start;
  padding-bottom: var(--s3);
  min-height: 460px;
}
.kb-col {
  display: flex; flex-direction: column; min-width: 0;
  max-height: calc(100vh - 280px);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
@media (max-width: 1100px) {
  .kanban {
    display: flex; grid-auto-flow: unset;
    overflow-x: auto; gap: var(--s3);
    scroll-snap-type: x proximity;
  }
  .kb-col { flex: 0 0 min(282px, 82vw); scroll-snap-align: start; }
}
/* ---- El estado se ve en el MARCO y en la CABECERA, no solo en el punto ----
   Pedido por Juan el 4-sep-2026 para el tablero de JIRA. El punto de la
   cabecera mide 8 px: hay que ir a buscarlo, y en una columna llena de
   tarjetas grises la vista no encuentra dónde empieza «En revisión».

   `--col` lo pone la vista con el color del estado YA RESUELTO para el tema
   activo (`JIRA.colColor`), igual que el punto. Aquí no se decide ningún
   color: se decide cuánto de ese color entra en cada superficie, y se hace
   con `color-mix` contra los tokens en vez de con opacidad, porque el mismo
   porcentaje sobre `--surface-2` claro y oscuro da dos tintes distintos y
   correctos sin escribir la regla dos veces.

   Los porcentajes son bajos a propósito: la columna sigue siendo un contenedor
   neutro donde se leen tarjetas, no un bloque de color. Lo que se busca es
   reconocer la columna de un vistazo, no teñir el tablero.

   Va con clase `is-tinted` y no sobre `.kb-col` a secas porque la misma
   carcasa la usan otros tres tableros —Mi tablero, Open Test y la ficha de
   personas—, y solo se pidió este.

   ORDEN IMPORTANTE: esto va ANTES de `.is-over` y de `.is-drop-col`, que
   tienen la misma especificidad. Mientras se arrastra manda el azul de
   destino; si estas reglas fueran después, la columna teñida se quedaría con
   su color y no habría forma de ver dónde va a caer la tarjeta. */
.kb-col.is-tinted { border-color: color-mix(in srgb, var(--col) 34%, var(--border)); }
.kb-col.is-tinted .kb-col-head {
  background: color-mix(in srgb, var(--col) 10%, transparent);
  border-bottom-color: color-mix(in srgb, var(--col) 30%, var(--border-soft));
  /* Menos 1 px: la cabecera vive DENTRO del borde de la columna, y con el
     mismo radio que ella asomaría una uña del fondo por cada esquina. */
  border-radius: calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px) 0 0;
}
.kb-col.is-tinted .kb-col-head h4 { color: color-mix(in srgb, var(--col) 45%, var(--ink)); }
.kb-col.is-tinted .kb-col-head .n {
  background: color-mix(in srgb, var(--col) 16%, var(--surface-3));
  color: color-mix(in srgb, var(--col) 55%, var(--ink-3));
}

.kb-col.is-over { background: var(--primary-soft); border-color: var(--primary); border-style: dashed; }
.kb-col-head {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--border-soft);
}
.kb-col-head .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.kb-col-head h4 { font-size: var(--fs-sm); font-weight: 700; letter-spacing: .01em; }
.kb-col-head .n {
  padding: 1px 7px; font-size: var(--fs-2xs); font-weight: 700;
  background: var(--surface-3); color: var(--ink-3); border-radius: var(--r-full);
  font-variant-numeric: tabular-nums;
}
.kb-col-head .wip { font-size: var(--fs-2xs); color: var(--warning); font-weight: 600; }
.kb-cards {
  flex: 1 1 auto; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--s2);
  padding: var(--s3); min-height: 90px;
}
/* ---- El final de la columna cuando hay más tarjetas de las que caben ----
   Pedido por Juan el 4-sep-2026: «ese borde no es bonito y está muy pegado al
   Añadir». Eran dos cosas distintas juntas.

   La primera, el aire: el botón salía a ras del listado, así que la última
   tarjeta y el «Añadir» se leían como una sola pieza. Ahora hay un escalón.

   La segunda, el corte: `.kb-cards` recorta a ras y la última tarjeta aparecía
   partida por una línea recta, que parece un fallo de pintado y no «hay más
   abajo». Se resuelve con un degradado del color de la columna encima del
   final del listado.

   Va en `::before` del botón y no en `.kb-cards::after` porque un pseudo
   dentro de un contenedor con `overflow` se desplaza CON el contenido: se
   vería en el fondo del scroll, no en el borde de la ventana. Colgado del
   botón, que es su hermano de abajo y no se mueve, queda siempre en el sitio.

   Y no hace falta apagarlo cuando la columna va corta: el degradado va de
   `--surface-2` —el fondo de la propia columna— a transparente, así que sobre
   una columna con pocas tarjetas es del mismo color que lo que tapa y no se
   ve. `pointer-events: none` para que no robe el clic de la última tarjeta. */
.kb-add { margin: var(--s2) var(--s3) var(--s3); position: relative; }
.kb-add::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 100%;
  height: 22px; pointer-events: none;
  background: linear-gradient(to top, var(--surface-2), transparent);
}

.kb-card {
  padding: var(--s3);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: grab; text-align: left; width: 100%;
  transition: box-shadow var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.kb-card:hover { border-color: var(--border-strong); transform: translateY(-1px); }
.kb-card:active { cursor: grabbing; }
.kb-card.is-dragging { opacity: .38; transform: rotate(1.5deg) scale(.99); }
.kb-card-labels { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 7px; }
.kb-label {
  height: 6px; width: 30px; border-radius: var(--r-full);
}
.kb-card h5 { font-size: var(--fs-md); font-weight: 600; line-height: 1.35; }
.kb-card .desc { margin-top: 4px; font-size: var(--fs-xs); color: var(--ink-3); }
.kb-card-meta {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  margin-top: var(--s3);
}
.kb-meta-i { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-2xs); color: var(--ink-3); font-weight: 500; }
.kb-meta-i svg { width: 13px; height: 13px; }
.kb-meta-i[data-tone="danger"] { color: var(--danger); }
.kb-meta-i[data-tone="warning"] { color: var(--warning); }
.kb-card .prio {
  width: 3px; border-radius: var(--r-full); align-self: stretch;
}
.kb-drop {
  height: 3px; margin: 2px 0; border-radius: 3px; background: var(--primary);
  animation: fade-in .1s both;
}

.prio-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.prio-alta   { background: var(--danger); }
.prio-media  { background: var(--warning); }
.prio-baja   { background: var(--ink-4); }
.prio-critica { background: var(--danger); box-shadow: 0 0 0 3px var(--danger-soft); }

/* Checklist en el detalle de tarjeta */
.checklist { display: flex; flex-direction: column; gap: 2px; }
.cl-item {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: 7px var(--s2); border-radius: var(--r-xs);
  font-size: var(--fs-md); cursor: pointer;
}
.cl-item:hover { background: var(--surface-2); }
.cl-item.is-done span.tx { color: var(--ink-4); text-decoration: line-through; }

/* ========================================================== ORGANIGRAMA = */
.org-wrap {
  position: relative; overflow: auto;
  background:
    radial-gradient(circle at 1px 1px, var(--border) 1px, transparent 0) 0 0 / 22px 22px;
  border: 1px solid var(--border); border-radius: var(--r-lg);
  min-height: 560px; padding: var(--s7) var(--s6);
}
.org-canvas {
  display: inline-block; min-width: 100%;
  transform-origin: top center;
  transition: transform var(--t) var(--ease-out);
}
.org-zoom {
  position: absolute; right: var(--s4); top: var(--s4); z-index: 3;
  display: flex; align-items: center; gap: 2px; padding: 3px;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-sm);
}
.org-zoom .z-val { min-width: 42px; text-align: center; font-size: var(--fs-2xs); font-weight: 600; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* Árbol con conectores puramente CSS (patrón de listas anidadas). */
.org-tree, .org-tree ul { display: flex; justify-content: center; list-style: none; padding: 0; margin: 0; }
.org-tree ul { padding-top: 26px; position: relative; }
.org-tree li {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  padding: 26px var(--s2) 0;
}
/* Media línea horizontal a cada lado del nodo */
.org-tree li::before,
.org-tree li::after {
  content: ""; position: absolute; top: 0; right: 50%;
  width: 50%; height: 26px;
  border-top: 2px solid var(--border-strong);
}
.org-tree li::after { right: auto; left: 50%; border-left: 2px solid var(--border-strong); }
/* Hijo único: solo la línea vertical */
.org-tree li:only-child { padding-top: 26px; }
.org-tree li:only-child::before { display: none; }
.org-tree li:only-child::after { left: 50%; width: 0; }
/* Extremos: se redondean y no sobresalen */
.org-tree li:first-child::before { border: 0 none; }
.org-tree li:last-child::after { border: 0 none; }
.org-tree li:last-child::before { border-right: 2px solid var(--border-strong); border-radius: 0 6px 0 0; }
.org-tree li:first-child::after { border-radius: 6px 0 0 0; }
/* Raíz sin conectores hacia arriba */
.org-tree > li { padding-top: 0; }
.org-tree > li::before, .org-tree > li::after { display: none; }
/* Bajada desde el padre hacia la fila de hijos */
.org-tree ul::before {
  content: ""; position: absolute; top: 0; left: 50%;
  width: 0; height: 26px;
  border-left: 2px solid var(--border-strong);
}

.org-node {
  position: relative;
  display: flex; align-items: center; gap: var(--s3);
  width: 236px; padding: var(--s3);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md);
  text-align: left;
  transition: all var(--t-fast) var(--ease);
}
.org-node:hover { border-color: var(--primary); transform: translateY(-2px); }
.org-node.is-me { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.org-node.is-match { border-color: var(--warning); box-shadow: 0 0 0 3px var(--warning-soft); }
.org-node .nm { font-size: var(--fs-sm); font-weight: 600; line-height: 1.3; }
.org-node .rl { font-size: var(--fs-2xs); color: var(--ink-3); line-height: 1.3; margin-top: 1px; }
.org-node .team-bar {
  position: absolute; left: 0; top: 12px; bottom: 12px; width: 3px;
  border-radius: 0 3px 3px 0;
}
.org-toggle {
  position: absolute; bottom: -11px; left: 50%; transform: translateX(-50%);
  display: grid; place-items: center; z-index: 2;
  width: 22px; height: 22px;
  font-size: var(--fs-2xs); font-weight: 700;
  color: var(--ink-3); background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: 50%;
  font-variant-numeric: tabular-nums;
}
.org-toggle:hover { border-color: var(--primary); color: var(--primary); }

/* Vista por equipos */
.team-card-head { display: flex; align-items: center; gap: var(--s3); }
.team-swatch { width: 10px; height: 34px; border-radius: var(--r-full); flex: none; }

/* ============================================================ CALENDARIO */
.cal-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  border: 1px solid var(--border); border-radius: var(--r-lg);
  overflow: hidden; background: var(--border);
  gap: 1px;
}
.cal-dow {
  padding: var(--s3) var(--s3);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-4); background: var(--surface-2); text-align: center;
}
.cal-day {
  position: relative;
  min-height: 118px; padding: 7px;
  background: var(--surface);
  display: flex; flex-direction: column; gap: 3px;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease);
}
.cal-day:hover { background: var(--surface-2); }
.cal-day.is-out { background: var(--surface-inset); }
.cal-day.is-out .cal-num { color: var(--ink-4); }
.cal-day.is-weekend .cal-num { color: var(--ink-3); }
.cal-day.is-today .cal-num {
  background: var(--primary); color: var(--primary-ink);
  border-radius: var(--r-full);
}
.cal-day.is-holiday { background: var(--danger-soft); }
.cal-day.is-selected { box-shadow: inset 0 0 0 2px var(--primary); }
.cal-num {
  display: grid; place-items: center;
  width: 24px; height: 24px; flex: none;
  font-size: var(--fs-xs); font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}
.cal-ev {
  display: flex; align-items: center; gap: 5px;
  padding: 2px 6px;
  font-size: var(--fs-2xs); font-weight: 500; line-height: 1.4;
  border-radius: 5px; background: var(--surface-3); color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-ev .ev-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.cal-more { font-size: var(--fs-2xs); color: var(--ink-4); font-weight: 600; padding-left: 6px; }
@media (max-width: 780px) {
  .cal-day { min-height: 74px; }
  .cal-ev { padding: 1px 4px; font-size: 9px; }
}

.cal-agenda-day {
  display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: var(--s4);
  padding: var(--s4) 0; border-bottom: 1px solid var(--border-soft);
}
.cal-agenda-day:last-child { border-bottom: 0; }
.cal-agenda-date { text-align: right; }
.cal-agenda-date .d { font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 600; line-height: 1; }
.cal-agenda-date .m { font-size: var(--fs-2xs); color: var(--ink-3); text-transform: uppercase; letter-spacing: .06em; font-weight: 600; }
.cal-agenda-date.is-today .d { color: var(--primary); }

.ev-row {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3); border-radius: var(--r-sm);
  transition: background var(--t-fast) var(--ease);
}
.ev-row:hover { background: var(--surface-2); }
.ev-bar { width: 3px; align-self: stretch; border-radius: var(--r-full); flex: none; }

/* ---- Choque de nombres con el calendario emergente ----
   components.css usa `.cal-grid`, `.cal-dow` y `.cal-day` para el calendario
   de los campos de fecha, y la rejilla mensual de esta vista usa los mismos
   nombres. Como esas reglas cargan antes pero tienen la misma especificidad,
   la mitad de sus valores se colaban aquí: el día elegido salía relleno de
   azul sólido, los números centrados y los días de otro mes al 50 %. La
   rejilla mensual vive siempre dentro de `.view`; el emergente cuelga de
   <body>. Con ese ancestro cada uno recupera lo suyo. */
.view .cal-grid .cal-day {
  height: auto; border-radius: 0; opacity: 1;
  align-items: stretch; justify-content: flex-start;
  font-size: inherit; color: inherit; font-weight: inherit;
}
.view .cal-grid .cal-day:hover { background: var(--surface-2); color: inherit; }
.view .cal-grid .cal-day.is-out { background: var(--surface-inset); }
.view .cal-grid .cal-day.is-out:hover { background: var(--surface-3); }
.view .cal-grid .cal-day.is-holiday { background: var(--danger-soft); }
.view .cal-grid .cal-day.is-selected {
  background: var(--primary-soft); box-shadow: inset 0 0 0 2px var(--primary);
}
.view .cal-grid .cal-day.is-selected:hover { background: var(--primary-soft-2); }
.view .cal-grid .cal-dow { padding: var(--s3); font-size: var(--fs-2xs); color: var(--ink-4); }

/* Y a la inversa: el emergente no hereda la rejilla con bordes de la vista. */
.cal-pop .cal-grid { border: 0; border-radius: 0; background: transparent; gap: 2px; overflow: visible; }
.cal-pop .cal-dow { background: transparent; padding: 3px 0 5px; }
.cal-pop .cal-day { min-height: 0; padding: 0; background: transparent; flex-direction: row; gap: 0; }
.cal-pop .cal-day:hover { background: var(--primary-soft); }
.cal-pop .cal-day.is-out { background: transparent; }
.cal-pop .cal-day.is-selected { background: var(--primary); }
.cal-pop .cal-day.is-selected:hover { background: var(--primary-hover); }

/* ======================================================== MALLA HORARIOS */
.sched {
  display: grid;
  grid-template-columns: 232px repeat(7, minmax(96px, 1fr));
  gap: 1px; background: var(--border);
  border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden;
  min-width: 900px;
}
.sched-h {
  padding: var(--s3);
  background: var(--surface-2);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-4); text-align: center;
}
.sched-h.is-today { color: var(--primary); background: var(--primary-soft); }
.sched-h .dnum { display: block; font-size: var(--fs-md); color: var(--ink-2); letter-spacing: 0; margin-top: 2px; text-transform: none; }
.sched-h.is-today .dnum { color: var(--primary); }
.sched-name {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s3); background: var(--surface);
  position: sticky; left: 0; z-index: 2;
}
.sched-name .nm { font-size: var(--fs-sm); font-weight: 600; line-height: 1.25; }
.sched-name .rl { font-size: var(--fs-2xs); color: var(--ink-3); line-height: 1.25; }
.sched-cell {
  padding: 5px; background: var(--surface);
  display: flex; flex-direction: column; gap: 3px; justify-content: center;
  min-height: 56px;
}
.shift {
  padding: 5px 7px; border-radius: var(--r-xs);
  font-size: var(--fs-2xs); font-weight: 600; line-height: 1.3;
  border-left: 3px solid transparent;
  cursor: pointer;
  transition: filter var(--t-fast) var(--ease);
}
.shift:hover { filter: brightness(1.04); }
.shift .h { display: block; font-weight: 500; opacity: .8; font-variant-numeric: tabular-nums; }
.sched-legend { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); }

.coverage-bar { display: flex; gap: 2px; height: 5px; border-radius: var(--r-full); overflow: hidden; }

/* ============================================================== CURSOS = */
.course-card { display: flex; flex-direction: column; overflow: hidden; }
.course-top {
  position: relative;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: var(--s4) var(--s5);
  color: #fff;
}
.course-top::before { content: ""; position: absolute; inset: 0; opacity: .92; }
.course-top > * { position: relative; }
.course-cat {
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: rgba(255, 255, 255, .82);
}
.course-code { font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 600; letter-spacing: -.01em; }
.course-body { flex: 1; padding: var(--s4) var(--s5); display: flex; flex-direction: column; gap: var(--s3); }
.course-body h4 { font-size: var(--fs-md); line-height: 1.35; }
.course-meta { display: flex; flex-wrap: wrap; gap: var(--s3); font-size: var(--fs-xs); color: var(--ink-3); }
.course-meta span { display: inline-flex; align-items: center; gap: 4px; }
.course-meta svg { width: 13px; height: 13px; }
.course-foot { padding: var(--s3) var(--s5); border-top: 1px solid var(--border-soft); background: var(--surface-2); }

.cert-card {
  display: flex; align-items: center; gap: var(--s4);
  padding: var(--s4);
}
.cert-seal {
  display: grid; place-items: center; flex: none;
  width: 54px; height: 54px; border-radius: var(--r-md);
  background: var(--primary-soft); color: var(--primary);
  font-family: var(--font-display); font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: .02em;
}

/* Lección / módulo */
.lesson {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); border-radius: var(--r-sm);
  border: 1px solid var(--border-soft);
}
.lesson + .lesson { margin-top: 6px; }
.lesson .n {
  display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: 50%;
  font-size: var(--fs-2xs); font-weight: 700;
  background: var(--surface-3); color: var(--ink-3);
}
.lesson.is-done .n { background: var(--success); color: #fff; }
.lesson.is-done .tt { color: var(--ink-3); }

/* ========================================================== DOCUMENTOS = */
.doc-row {
  display: grid; grid-template-columns: 42px minmax(0, 1fr) auto; gap: var(--s3);
  align-items: center; padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--border-soft);
  transition: background var(--t-fast) var(--ease);
}
.doc-row:last-child { border-bottom: 0; }
.doc-row:hover { background: var(--surface-2); }
.doc-ico {
  display: grid; place-items: center; width: 38px; height: 38px;
  border-radius: var(--r-sm); background: var(--surface-3); color: var(--ink-3);
}
.doc-ico svg { width: 18px; height: 18px; }
.doc-ico[data-t="pdf"]   { background: var(--danger-soft); color: var(--danger); }
.doc-ico[data-t="doc"]   { background: var(--primary-soft); color: var(--primary); }
.doc-ico[data-t="sheet"] { background: var(--success-soft); color: var(--success); }
.doc-ico[data-t="slide"] { background: var(--warning-soft); color: var(--warning); }
.doc-meta { display: flex; flex-wrap: wrap; gap: var(--s3); font-size: var(--fs-xs); color: var(--ink-3); margin-top: 2px; }

.doc-viewer {
  padding: var(--s5); background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--r-md);
  font-size: var(--fs-md); line-height: 1.7; color: var(--ink-2);
}
.doc-viewer h4 { margin: var(--s5) 0 var(--s2); font-size: var(--fs-base); color: var(--ink); }
.doc-viewer h4:first-child { margin-top: 0; }
.doc-viewer p + p { margin-top: var(--s3); }
.doc-viewer ol { list-style: decimal; padding-left: var(--s5); display: flex; flex-direction: column; gap: 6px; }
.doc-viewer ul { list-style: disc; padding-left: var(--s5); display: flex; flex-direction: column; gap: 6px; }

/* ======================================================= FICHA EMPLEADO = */
.emp-hero {
  position: relative; overflow: hidden;
  border-radius: var(--r-lg);
  border: 1px solid var(--border);
  background: var(--surface);
}
/* Portada en el azul de la empresa. Juan, 11-sep-2026: «que tenga un color
   azul, tipo gradiente, algo bonito, para que se note más». Tres capas: el
   degradado de marino a azul, dos luces suaves en las esquinas y, a la
   derecha, los anillos finos del isotipo. Colores fijos a propósito: la
   portada es la misma en el tema claro y en el oscuro, y ningún texto se
   apoya en ella. */
.emp-cover {
  position: relative; height: 150px; overflow: hidden;
  background:
    radial-gradient(55% 130% at 92% -20%, rgba(20, 196, 237, .55), transparent 62%),
    radial-gradient(45% 110% at 6% 125%, rgba(77, 134, 255, .5), transparent 66%),
    linear-gradient(115deg, #041552 0%, #0a2fa8 42%, #003bc8 64%, #1a7fe8 100%);
}
.emp-cover::before {
  content: ""; position: absolute; inset: 0;
  background: repeating-linear-gradient(115deg, rgba(255, 255, 255, .055) 0 1px, transparent 1px 24px);
  -webkit-mask-image: linear-gradient(90deg, transparent 20%, #000 70%);
          mask-image: linear-gradient(90deg, transparent 20%, #000 70%);
}
.emp-cover::after {
  content: ""; position: absolute; right: -70px; top: -120px;
  width: 340px; height: 340px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .16);
  box-shadow: 0 0 0 38px rgba(255, 255, 255, .035), 0 0 0 76px rgba(255, 255, 255, .025);
}

/* Solo el avatar invade la portada. El nombre y los datos viven sobre la
   superficie clara: antes el bloque entero subía y el texto quedaba oscuro
   sobre oscuro, ilegible. */
.emp-hero-body {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--s3) var(--s5);
  padding: 0 var(--s6) var(--s5);
  position: relative;
}
/* ---- Cambiar la foto de perfil ----
   El disparador es el propio avatar: la cámara solo aparece al pasar por
   encima, para que la ficha no lleve un botón permanente sobre la cara. */
.emp-photo {
  position: relative; display: inline-block; cursor: pointer;
  grid-row: 1; align-self: start; margin-top: -112px;
}
.emp-photo > .avatar { margin-top: 0; }
.emp-photo-ov {
  position: absolute; inset: 0; z-index: 2;
  display: grid; place-items: center;
  border-radius: var(--r-full);
  background: rgba(13, 16, 32, .55); color: #fff;
  opacity: 0; transition: opacity var(--t-fast) var(--ease);
}
.emp-photo-ov svg { width: 28px; height: 28px; }
.emp-photo:hover .emp-photo-ov,
.emp-photo:focus-within .emp-photo-ov { opacity: 1; }

/* La foto, al doble (Juan, 11-sep-2026): 224 px en vez de 112. Monta la mitad
   sobre la portada, con un aro del color de la tarjeta y una sombra que la
   despega del azul. Solo aquí: `.avatar-2xl` sigue midiendo lo mismo fuera. */
.emp-hero .avatar-2xl { width: 224px; height: 224px; font-size: 64px; }
.emp-hero-body > .avatar,
.emp-photo > .avatar { box-shadow: 0 0 0 5px var(--surface), 0 12px 32px rgba(5, 9, 45, .28); }
.emp-hero-body > .avatar {
  grid-row: 1; align-self: start;
  margin-top: -112px;
}
.emp-id { grid-row: 1; padding-top: var(--s4); min-width: 0; }
.emp-hero-actions { grid-row: 1; padding-bottom: 2px; }

/* En pantalla estrecha la foto baja a 128 px: a 224 se comería el ancho. */
@media (max-width: 900px) {
  .emp-cover { height: 112px; }
  .emp-hero .avatar-2xl { width: 128px; height: 128px; font-size: var(--fs-3xl); }
  .emp-hero-body { grid-template-columns: minmax(0, 1fr); }
  .emp-hero-body > .avatar, .emp-photo { grid-row: 1; margin-top: -64px; }
  .emp-id { grid-row: 2; padding-top: var(--s2); }
  .emp-hero-actions { grid-row: 3; padding-bottom: 0; }
}
.emp-id h1 { font-size: var(--fs-2xl); letter-spacing: -.028em; }
.emp-id .role { font-size: var(--fs-md); color: var(--ink-2); margin-top: 2px; }
.emp-id .meta { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); margin-top: var(--s3); font-size: var(--fs-xs); color: var(--ink-3); }
.emp-id .meta span { display: inline-flex; align-items: center; gap: 5px; }
.emp-id .meta svg { width: 14px; height: 14px; }
.emp-hero-actions { display: flex; gap: var(--s2); flex-wrap: wrap; padding-bottom: 2px; }

.note {
  display: flex; gap: var(--s3);
  padding: var(--s4);
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface);
}
.note + .note { margin-top: var(--s3); }
.note .n-side { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: none; }
.note .n-kind {
  display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: var(--r-sm); background: var(--surface-3); color: var(--ink-3);
}
.note .n-kind svg { width: 17px; height: 17px; }
.note .n-kind[data-k="reconocimiento"] { background: var(--success-soft); color: var(--success); }
.note .n-kind[data-k="llamado"]        { background: var(--danger-soft);  color: var(--danger); }
.note .n-kind[data-k="1a1"]            { background: var(--primary-soft); color: var(--primary); }
.note .n-kind[data-k="plan"]           { background: var(--warning-soft); color: var(--warning); }
.note .n-kind[data-k="nota"]           { background: var(--neutral-soft); color: var(--ink-3); }
.note.is-private { border-color: var(--accent); }

.action-item {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3); border-radius: var(--r-sm);
  border: 1px solid var(--border-soft);
}
.action-item + .action-item { margin-top: 6px; }
.action-item.is-done .tx { text-decoration: line-through; color: var(--ink-4); }

/* ------------------------------------------------ Historial (0120) -----
   La línea de tiempo de la ficha. Dos colores y solo dos, como los pidió
   Juan: rojo lo anterior al contrato vigente, verde lo que corre desde él.
   Salen de `--danger` y `--success`, que ya están afinados para cada tema. El
   tipo de registro lo dice el icono del punto, no otro color. */
.hist-item, .hist-ytag, .hist-today, .hist-chip, .hist-legend > span,
.hist-sum-row > span, .ev-era { --hc: var(--success); --hc-soft: var(--success-soft); }
.hist-item[data-era="prev"], .hist-ytag[data-era="prev"], .hist-today[data-era="prev"],
.hist-chip[data-era="prev"], .hist-legend > [data-era="prev"],
.hist-sum-row > [data-era="prev"], .ev-era[data-era="prev"] { --hc: var(--danger); --hc-soft: var(--danger-soft); }

.hist-legend { display: inline-flex; align-items: center; gap: var(--s3); font-size: var(--fs-xs); color: var(--ink-3); white-space: nowrap; }
.hist-legend > span, .hist-sum-row > span { display: inline-flex; align-items: center; gap: 6px; }
.hist-legend i, .hist-sum-row i, .hist-chip i, .ev-era i {
  flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--hc);
}

/* La franja de arriba: cuánto tiempo es anterior y cuánto actual. */
.hist-sum {
  display: flex; flex-direction: column; gap: var(--s2);
  padding: var(--s3) var(--s4); margin-bottom: var(--s4);
  background: var(--surface-2); border: 1px solid var(--border-soft); border-radius: var(--r-md);
}
.hist-sum.is-flat { flex-direction: row; align-items: center; font-size: var(--fs-xs); color: var(--ink-3); }
.hist-sum.is-flat svg { flex: none; width: 15px; height: 15px; }
.hist-bar { display: flex; gap: 3px; height: 6px; }
.hist-bar > span {
  display: block; flex-basis: 0; min-width: 6px; border-radius: var(--r-full); transform-origin: left center;
}
.hist-bar .hb-prev { background: var(--danger); }
.hist-bar .hb-now { background: var(--success); }
.hist-sum.is-in .hist-bar > span { animation: histGrow .8s var(--ease-out) backwards; }
.hist-sum.is-in .hist-bar .hb-now { animation-delay: .12s; }
.hist-sum-row {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--s1) var(--s4);
  font-size: var(--fs-xs); color: var(--ink-3);
}
.hist-sum-row b { margin-right: 2px; font-weight: 600; color: var(--ink); }

/* Filtro por año. Cada año lleva el punto de su época; si tiene de las dos,
   mitad y mitad. El elegido va en el azul de la empresa: es el único detalle
   de marca de la línea. */
.hist-filter { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: var(--s4); }
.hist-chip {
  display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 6px 0 10px;
  font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink-2);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-full); cursor: pointer;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.hist-chip:not([data-era]) { padding-left: 12px; }
.hist-chip:hover { border-color: var(--border-strong); background: var(--surface-2); }
.hist-chip .n {
  min-width: 20px; padding: 1px 6px; border-radius: var(--r-full); text-align: center;
  font-size: var(--fs-2xs); font-weight: 700; color: var(--ink-3); background: var(--surface-3);
}
.hist-chip[data-era="mix"] i { background: linear-gradient(90deg, var(--danger) 50%, var(--success) 50%); }
.hist-chip.is-active { color: var(--primary-ink); background: var(--primary); border-color: var(--primary); }
.hist-chip.is-active .n { color: inherit; background: rgba(255, 255, 255, .2); }
.hist-chip.is-active i { box-shadow: 0 0 0 2px rgba(255, 255, 255, .85); }

/* La línea. Cada pieza pinta su tramo con el color de su época, y por eso el
   cambio de color cae justo en el inicio del contrato. */
.hist { position: relative; display: flex; flex-direction: column; }
.hist > [hidden] { display: none; }
.hist > * { position: relative; padding-left: 44px; }
.hist > *::before {
  content: ""; position: absolute; left: 14px; top: 0; bottom: 0; width: 2px;
  background: var(--hc, var(--success)); opacity: .5;
}
.hist > .is-first::before { top: 21px; }
.hist > .is-last::before { bottom: auto; height: 21px; }
.hist > .is-first.is-last::before { display: none; }

.hist-item { padding-bottom: var(--s3); }
.hist-dot {
  position: absolute; left: 0; top: 6px; z-index: 1;
  display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%;
  color: var(--hc); background: var(--surface); border: 2px solid var(--hc);
  box-shadow: 0 0 0 4px var(--surface);
  transition: transform .2s var(--ease-out), background .2s var(--ease-out);
}
.hist-dot svg { width: 14px; height: 14px; }
.hist-box {
  min-width: 0; padding: 10px 14px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  box-shadow: inset 3px 0 0 var(--hc);
  transition: transform .2s var(--ease-out), box-shadow .2s var(--ease-out);
}
.hist-item[data-era="prev"] .hist-box { background: var(--surface-2); }
.hist-item:hover .hist-dot { transform: scale(1.1); background: var(--hc-soft); }
.hist-item:hover .hist-box { transform: translateX(3px); box-shadow: inset 3px 0 0 var(--hc), var(--shadow-sm); }
.hist-top { display: flex; flex-wrap: wrap; align-items: center; gap: 6px var(--s2); }
.hist-kind { font-size: var(--fs-md); font-weight: 600; color: var(--ink); }
.hist-tag {
  padding: 1px 7px; border-radius: var(--r-full);
  font-size: var(--fs-2xs); font-weight: 600; color: var(--ink-3); background: var(--surface-3);
}
.hist-tag.is-future { color: var(--info); background: var(--info-soft); }
.hist-date {
  margin-left: auto; white-space: nowrap; font-variant-numeric: tabular-nums;
  font-size: var(--fs-xs); font-weight: 600; color: var(--hc);
}
.hist-tx { margin-top: 4px; font-size: var(--fs-sm); color: var(--ink-2); white-space: pre-wrap; overflow-wrap: anywhere; }
.hist-meta {
  display: flex; align-items: center; gap: 6px; min-height: 30px; margin-top: var(--s2);
  font-size: var(--fs-2xs); color: var(--ink-4);
}
.hist-act { display: inline-flex; gap: 2px; margin-left: auto; opacity: 0; transition: opacity var(--t-fast) var(--ease); }
.hist-item:hover .hist-act, .hist-act:focus-within { opacity: 1; }

/* Lo programado todavía no pasó, y se dibuja punteado. */
.hist-item.is-future .hist-box, .hist-item.is-future .hist-dot { border-style: dashed; }
.hist > .hist-item.is-future::before, .hist > .hist-ytag.is-future::before {
  background: repeating-linear-gradient(to bottom, var(--hc) 0 4px, transparent 4px 8px);
}

/* La etiqueta del año va montada sobre la línea. */
.hist > .hist-ytag { padding-left: 0; padding-bottom: var(--s3); }
.hist-ytag > span {
  position: relative; z-index: 1; display: inline-block; padding: 2px 10px;
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .04em; font-variant-numeric: tabular-nums;
  color: var(--ink-2); background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-full);
}
.hist-ytag.is-future > span { color: var(--info); background: var(--info-soft); border-color: transparent; }

/* «Hoy»: el punto que late es el presente, y la línea baja desde ahí. */
.hist-today {
  display: flex; align-items: center; min-height: 30px; padding-bottom: var(--s2);
  font-size: var(--fs-xs); font-weight: 700; color: var(--success);
}
.hist-pulse {
  position: absolute; left: 9px; top: 9px; z-index: 1; width: 12px; height: 12px; border-radius: 50%;
  background: var(--success); box-shadow: 0 0 0 4px var(--surface);
}
.hist-pulse::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background: var(--success); animation: histPulse 2.2s var(--ease-out) infinite;
}

/* El inicio del contrato: donde el verde se vuelve rojo. */
.hist-cut { display: flex; align-items: center; gap: var(--s2); padding-bottom: var(--s3); }
.hist > .hist-cut::before { background: linear-gradient(to bottom, var(--success), var(--danger)); opacity: .7; }
.hist-cut::after {
  content: ""; position: absolute; left: 9px; top: 5px; width: 12px; height: 12px; border-radius: 2px;
  transform: rotate(45deg); background: linear-gradient(135deg, var(--success) 50%, var(--danger) 50%);
  box-shadow: 0 0 0 3px var(--surface);
}
.hc-pill {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: var(--r-full);
  white-space: nowrap; font-size: var(--fs-2xs); font-weight: 700; color: var(--success); background: var(--success-soft);
}
.hc-pill svg { width: 12px; height: 12px; }
.hc-line { flex: 1; border-top: 1px dashed var(--border-strong); }

/* La versión del Resumen: más apretada, sin autor ni botones. */
.hist.is-compact .hist-item { padding-bottom: var(--s2); }
.hist.is-compact .hist-box { padding: 8px 12px; }
.hist.is-compact .hist-tx { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.hist-more { margin-top: var(--s2); padding-left: 44px; font-size: var(--fs-xs); color: var(--ink-4); }

/* Entrada escalonada al pintar y al cambiar de año. `backwards` deja cada
   pieza oculta solo mientras espera su turno: si la animación no corre —con
   movimiento reducido no corre—, todo se ve igual. */
.hist.is-in > *, .hist.is-refilter > * {
  animation: histIn .42s var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 40ms);
}
.hist.is-in > .hist-item .hist-dot, .hist.is-refilter > .hist-item .hist-dot {
  animation: histPop .45s var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 40ms + 90ms);
}
.hist-item.is-new .hist-box { animation: histFlash 1.8s var(--ease-out) .35s 1 backwards; }
@keyframes histIn { from { opacity: 0; transform: translateY(10px); } }
@keyframes histPop { from { opacity: 0; transform: scale(.4); } }
@keyframes histGrow { from { transform: scaleX(0); } }
@keyframes histPulse { from { opacity: .55; transform: scale(1); } to { opacity: 0; transform: scale(2.6); } }
@keyframes histFlash {
  0%   { box-shadow: inset 3px 0 0 var(--hc), 0 0 0 0 var(--hc-soft); }
  25%  { box-shadow: inset 3px 0 0 var(--hc), 0 0 0 6px var(--hc-soft); }
  100% { box-shadow: inset 3px 0 0 var(--hc), 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .hist.is-in > *, .hist.is-refilter > *,
  .hist.is-in > .hist-item .hist-dot, .hist.is-refilter > .hist-item .hist-dot,
  .hist-item.is-new .hist-box, .hist-sum.is-in .hist-bar > span, .hist-pulse::after { animation: none; }
}

/* Los dos botones de registrar. «Agregar acción» en el azul de la empresa
   porque es lo nuevo de la pestaña; «Agregar nota» a su lado, sin competir. */
.hist-add { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.hist-add-btn {
  display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s4); text-align: left;
  color: var(--ink); background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-card); cursor: pointer;
  transition: transform .2s var(--ease-out), box-shadow .2s var(--ease-out), border-color .2s var(--ease-out);
}
.hist-add-btn:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--border-strong); }
.hist-add-btn:active { transform: none; }
.hist-add-btn .ha-ico {
  display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: var(--r-md);
  color: var(--primary); background: var(--primary-soft);
}
.hist-add-btn .ha-ico svg { width: 18px; height: 18px; }
.hist-add-btn b { display: block; font-size: var(--fs-md); font-weight: 600; }
.hist-add-btn .ha-tx > span { display: block; margin-top: 2px; font-size: var(--fs-xs); line-height: 1.35; color: var(--ink-3); }
.hist-add-btn.is-brand { color: var(--primary-ink); background: var(--primary); border-color: var(--primary); }
.hist-add-btn.is-brand .ha-ico { color: inherit; background: rgba(255, 255, 255, .18); }
.hist-add-btn.is-brand .ha-tx > span { color: inherit; opacity: .82; }

/* El formulario de la acción: los tipos como fichas, todos a la vista. */
.ev-kinds { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s2); }
.ev-kind {
  position: relative; display: flex; align-items: center; gap: var(--s2); padding: 8px 10px;
  font-size: var(--fs-sm); font-weight: 500; color: var(--ink-2);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.ev-kind:hover { border-color: var(--border-strong); }
.ev-kind input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.ev-kind .ek-i {
  display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: var(--r-sm);
  color: var(--ink-3); background: var(--surface-3);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.ev-kind .ek-i svg { width: 15px; height: 15px; }
.ev-kind.is-on { color: var(--ink); font-weight: 600; background: var(--primary-soft); border-color: var(--primary); }
.ev-kind.is-on .ek-i { color: var(--primary-ink); background: var(--primary); }
.ev-kind:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }
.ev-hint { min-height: 1.3em; margin-top: var(--s2); }
.ev-era {
  display: flex; align-items: flex-start; gap: var(--s2); margin: calc(var(--s2) * -1) 0 var(--s4);
  padding: 9px 12px; border-radius: var(--r-md);
  font-size: var(--fs-xs); font-weight: 500; color: var(--hc); background: var(--hc-soft);
}
.ev-era:empty { display: none; }
.ev-era i { margin-top: 4px; }

/* ------------------------------------------- Ajuste manual de horas (0121)
   La barra del periodo de Tiempo y asistencia manda sobre los indicadores,
   la gráfica y el historial, y por eso va encima de los tres. */
.att-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); }
.att-range { font-size: var(--fs-xs); color: var(--ink-3); }
.adj-cell { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.adj-none { font-size: var(--fs-xs); color: var(--ink-4); }
.adj-delta { font-size: var(--fs-sm); font-weight: 700; font-variant-numeric: tabular-nums; }
.adj-delta.is-up { color: var(--success); }
.adj-delta.is-down { color: var(--danger); }

/* Sumar o restar: dos botones grandes; el elegido lleva el color de lo que hace. */
.adj-mode { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2); }
.adj-mode label {
  position: relative; display: flex; align-items: center; justify-content: center; gap: 6px; height: 40px;
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2); cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.adj-mode label svg { width: 16px; height: 16px; }
.adj-sign { font-size: 18px; font-weight: 700; line-height: 1; }
.adj-mode input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.adj-mode label:hover { border-color: var(--border-strong); }
.adj-mode label.is-on[data-m="add"] { color: var(--success); background: var(--success-soft); border-color: var(--success); }
.adj-mode label.is-on[data-m="sub"] { color: var(--danger); background: var(--danger-soft); border-color: var(--danger); }
.adj-mode label:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }

/* Lo marcado ese día y en qué queda con el ajuste: la cuenta a la vista. */
.adj-sum {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3); min-height: 38px;
  padding: 8px 12px; font-size: var(--fs-sm); color: var(--ink-2);
  background: var(--surface-2); border: 1px solid var(--border-soft); border-radius: var(--r-md);
}
.adj-sum:empty { display: none; }
.adj-sum b { font-variant-numeric: tabular-nums; color: var(--ink); }
.adj-sum.is-up b { color: var(--success); }
.adj-sum.is-down b { color: var(--danger); }
.adj-sum.is-bad { color: var(--danger); background: var(--danger-soft); border-color: transparent; }

/* ------------------------------------------------ Malla de horarios (0122)
   La leyenda es también el catálogo: a cada turno le sigue su lápiz, casi
   invisible hasta que se pasa por encima para no ensuciar la leyenda. */
.legend-edit {
  display: inline-grid; place-items: center; width: 22px; height: 22px; margin-left: 2px;
  color: var(--ink-4); background: transparent; border: 0; border-radius: var(--r-xs); cursor: pointer;
  opacity: .6; transition: opacity var(--t-fast) var(--ease), background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.legend-edit svg { width: 13px; height: 13px; }
.legend-item:hover .legend-edit, .legend-edit:focus-visible { opacity: 1; color: var(--ink); background: var(--surface-3); }
/* Inicio, fin y descanso del turno personalizado y del editor del catálogo. */
.sh-custom { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); margin-top: var(--s3); }
.sh-custom[hidden] { display: none; }
.sh-net { min-height: 1.3em; margin-top: var(--s2); font-size: var(--fs-xs); color: var(--ink-3); }

/* KPI compacto en ficha */
.kpi-mini {
  display: flex; flex-direction: column; gap: 3px;
  padding: var(--s3) var(--s4);
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-2);
}
.kpi-mini .lb { font-size: var(--fs-2xs); font-weight: 600; color: var(--ink-3); }
.kpi-mini .vl {
  font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 600;
  letter-spacing: -.02em; line-height: 1.15;
}

/* =============================================================== TI ==== */
.ticket-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--s3);
  align-items: center; padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--border-soft);
  transition: background var(--t-fast) var(--ease);
  text-align: left; width: 100%;
}
.ticket-row:last-child { border-bottom: 0; }
.ticket-row:hover { background: var(--surface-2); }
.ticket-key {
  font-family: var(--font-mono); font-size: var(--fs-2xs); font-weight: 600;
  color: var(--ink-4); letter-spacing: -.02em;
}
.sla-bar { width: 68px; height: 4px; border-radius: var(--r-full); background: var(--surface-3); overflow: hidden; }
.sla-bar > span { display: block; height: 100%; border-radius: var(--r-full); }

.asset-card { display: flex; align-items: center; gap: var(--s4); padding: var(--s4); }
.asset-ico {
  display: grid; place-items: center; flex: none;
  width: 46px; height: 46px; border-radius: var(--r-md);
  background: var(--surface-3); color: var(--ink-2);
}
.asset-ico svg { width: 22px; height: 22px; }

.app-tile {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4);
}
.app-logo {
  display: grid; place-items: center; flex: none;
  width: 40px; height: 40px; border-radius: var(--r-sm);
  font-family: var(--font-display); font-size: var(--fs-md); font-weight: 700;
  color: #fff;
}
.seats { display: flex; gap: 2px; height: 6px; border-radius: var(--r-full); overflow: hidden; background: var(--surface-3); }

/* ============================================================== PQRSF = */
.pqrsf-type {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  padding: var(--s4);
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface); text-align: left; width: 100%;
  transition: all var(--t-fast) var(--ease);
}
.pqrsf-type:hover { border-color: var(--border-strong); background: var(--surface-2); }
.pqrsf-type.is-active { border-color: var(--primary); background: var(--primary-soft); box-shadow: 0 0 0 3px var(--primary-soft); }
.pqrsf-type .ic {
  display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: var(--r-sm); background: var(--surface-3); color: var(--ink-2);
}
.pqrsf-type.is-active .ic { background: var(--surface); color: var(--primary); }
.pqrsf-type .ic svg { width: 17px; height: 17px; }
.pqrsf-type .tt { font-size: var(--fs-md); font-weight: 600; }
.pqrsf-type .ds { font-size: var(--fs-xs); color: var(--ink-3); }

/* ========================================================= SOLICITUDES = */
.req-steps { display: flex; align-items: center; gap: 0; }
.req-step { display: flex; align-items: center; gap: var(--s2); flex: 1; min-width: 0; }
.req-step .bullet {
  display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: 50%;
  font-size: var(--fs-2xs); font-weight: 700;
  background: var(--surface-3); color: var(--ink-4);
  border: 2px solid transparent;
}
.req-step .bullet svg { width: 14px; height: 14px; }
.req-step.is-done .bullet { background: var(--success); color: #fff; }
.req-step.is-current .bullet { background: var(--surface); color: var(--primary); border-color: var(--primary); }
.req-step.is-rejected .bullet { background: var(--danger); color: #fff; }
.req-step .lb { font-size: var(--fs-2xs); font-weight: 600; color: var(--ink-3); }
.req-step.is-done .lb, .req-step.is-current .lb { color: var(--ink); }
.req-step .line { flex: 1; height: 2px; background: var(--border); border-radius: 2px; min-width: 14px; }
.req-step.is-done .line { background: var(--success); }
.req-step:last-child .line { display: none; }

.balance-ring { display: flex; align-items: center; gap: var(--s5); }

/* --- Encuestas & Evaluaciones (31-ago-2026) --- */
.svy-q { padding: var(--s4) 0; }
.svy-q + .svy-q { border-top: 1px solid var(--border-soft); }
.svy-scale { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.svy-opt {
  min-width: 38px; height: 38px; padding: 0 var(--s2);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface); font-weight: 700; font-size: var(--fs-sm);
  color: var(--ink-2); cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.svy-opt:hover { border-color: var(--border-strong); background: var(--surface-2); }
.svy-opt.is-on { background: var(--primary); border-color: var(--primary); color: var(--primary-ink); }
.svy-nps .svy-opt { min-width: 32px; height: 32px; font-size: var(--fs-xs); }
.svy-scale-lb { flex-basis: 100%; }

/* --- Beneficios: administración (31-ago-2026) --- */
.ben-adm-people {
  max-height: 220px; overflow-y: auto;
  padding: var(--s3); border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-2);
}

/* --- Inicio corto (rediseño 31-ago-2026) --- */
/* El arte del saludo se APAGÓ el 2-sep-2026 —la atmósfera la ponía el lavado de
   color de `.hero-band`— y VUELVE el 5-sep-2026, porque ahora dice algo: es un
   cielo que cambia con la hora (Juan). Se enciende con cabeza:

   · Va detrás del texto (`z-index:0`; `.hero-band > *` ya pone 1 al resto) y
     pegado a la derecha, que es el lado que el saludo deja libre.
   · Se difumina hacia la izquierda con una máscara, para que no haya un borde
     recto cortando el degradado de la franja.
   · Es decoración: `pointer-events:none` para que no se coma ningún clic. */
.hb-art {
  position: absolute;
  inset: 0 0 0 auto;
  width: min(420px, 55%);
  height: 100%;
  z-index: 0;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 38%);
  mask-image: linear-gradient(to right, transparent, #000 38%);
}
/* En claro el cielo se insinúa; en oscuro puede subir, que es donde un cielo
   nocturno se ve de verdad. */
.hb-art { opacity: .55; }
[data-theme="dark"] .hb-art { opacity: .85; }
@media (max-width: 640px) { .hb-art { width: 62%; opacity: .35; } }

.home-card .card-body { display: flex; flex-direction: column; }
.home-card .hc-ico {
  display: grid; place-items: center; flex: none;
  width: 40px; height: 40px; border-radius: var(--r-lg);
}
.home-card .hc-ico svg { width: 19px; height: 19px; }
.home-card .hc-ico[data-tone="blue"]   { background: var(--info-soft); color: var(--info); }
.home-card .hc-ico[data-tone="purple"] { background: var(--accent-soft); color: var(--accent); }
.home-card .hc-ico[data-tone="green"]  { background: var(--success-soft); color: var(--success); }
.home-card .hc-main {
  font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 700;
  letter-spacing: -.02em; margin-bottom: 3px;
}
.home-card .hc-btn {
  margin-top: var(--s4); justify-content: center; gap: var(--s2);
  color: var(--primary);
}
.home-card .card-body > .t-sm { flex: 1; }

.home-quick { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s3); }
@media (max-width: 900px) { .home-quick { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* --- Ficha de persona (rediseño 31-ago-2026) --- */
.emp-band {
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--s4); padding: var(--s4) var(--s6);
  border-top: 1px solid var(--border-soft);
}
@media (max-width: 1100px) { .emp-band { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 640px)  { .emp-band { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.emp-band-cell .bl {
  font-size: var(--fs-xs); font-weight: 500; letter-spacing: 0; text-transform: none;
  color: var(--ink-4); margin-bottom: 4px;
}
.emp-band-cell .bv { font-size: var(--fs-sm); font-weight: 600; }
.emp-band-cell .bs { font-size: var(--fs-2xs); color: var(--ink-3); margin-top: 2px; }

.emp-kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); }
@media (max-width: 720px) { .emp-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.emp-kpi {
  padding: var(--s4); border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface);
}
.emp-kpi .ek-ico {
  display: grid; place-items: center; width: 26px; height: 26px;
  border-radius: var(--r-xs); background: var(--neutral-soft); color: var(--ink-3); flex: none;
}
.emp-kpi .ek-ico[data-tone="green"]  { background: var(--success-soft); color: var(--success); }
.emp-kpi .ek-ico[data-tone="blue"]   { background: var(--info-soft); color: var(--info); }
.emp-kpi .ek-ico[data-tone="purple"] { background: var(--accent-soft); color: var(--accent); }
.emp-kpi .ek-ico[data-tone="amber"]  { background: var(--warning-soft); color: var(--warning); }
.emp-kpi .ek-v {
  font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 700;
  letter-spacing: -.02em; margin-bottom: 2px;
}
.t-success { color: var(--success); }
.t-warn { color: var(--warning); }

.emp-doc-row { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) 0; }
.emp-doc-row + .emp-doc-row { border-top: 1px solid var(--border-soft); }
.emp-doc-ico {
  display: grid; place-items: center; flex: none;
  width: 32px; height: 32px; border-radius: var(--r-sm);
  background: var(--info-soft); color: var(--info);
}
.emp-nomore {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: var(--s5); text-align: center;
  background: var(--surface-2); border-radius: var(--r-md); color: var(--ink-4);
}

/* --- Panel de RRHH (rediseño 31-ago-2026) ---
   Dos filas de tres: el bloque ancho a la izquierda y dos columnas estrechas.
   `align-items: stretch` es lo que evita los huecos — las tres tarjetas de una
   fila miden lo mismo aunque una traiga menos contenido. */
.hr-row {
  display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--s5); align-items: stretch;
}
.hr-row > .card { height: 100%; }
/* La tarjeta que lleva un gráfico reparte el alto sobrante en vez de dejarlo
   en un hueco debajo: el cuerpo crece y el gráfico se centra. */
.hr-fill { display: flex; flex-direction: column; }
.hr-fill .card-body { flex: 1; display: flex; flex-direction: column; justify-content: center; }
@media (max-width: 1240px) { .hr-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
@media (max-width: 820px)  { .hr-row { grid-template-columns: minmax(0, 1fr); } }

.hr-kpi .card-body { display: flex; flex-direction: column; height: 100%; }
.hr-kpi-ico {
  display: grid; place-items: center; flex: none;
  width: 38px; height: 38px; border-radius: var(--r-lg);
  background: var(--neutral-soft); color: var(--ink-3);
}
.hr-kpi-ico svg { width: 19px; height: 19px; }
.hr-kpi-ico[data-tone="blue"]   { background: var(--info-soft);    color: var(--info); }
.hr-kpi-ico[data-tone="green"]  { background: var(--success-soft); color: var(--success); }
.hr-kpi-ico[data-tone="teal"]   { background: var(--success-soft); color: var(--success); }
.hr-kpi-ico[data-tone="amber"]  { background: var(--warning-soft); color: var(--warning); }
.hr-kpi-ico[data-tone="red"]    { background: var(--danger-soft);  color: var(--danger); }
.hr-kpi-ico[data-tone="purple"] { background: var(--accent-soft);  color: var(--accent); }
.hr-kpi-v {
  font-family: var(--font-display); font-size: var(--fs-3xl); font-weight: 700;
  line-height: 1.05; letter-spacing: -.03em;
}
.hr-kpi-link {
  display: flex; align-items: center; gap: 4px;
  margin-top: auto; padding-top: var(--s3);
  border-top: 1px solid var(--border-soft);
  font-size: var(--fs-xs); font-weight: 600; color: var(--primary);
}
/* El hueco del enlace se reserva aunque no haya enlace: sin esto, la tarjeta
   sin destino queda más corta y rompe la fila. */
.hr-kpi-link.is-empty { min-height: 19px; border-top-color: transparent; }
.hr-kpi-link[data-tone="green"]  { color: var(--success); }
.hr-kpi-link[data-tone="amber"]  { color: var(--warning); }
.hr-kpi-link[data-tone="red"]    { color: var(--danger); }
.hr-kpi-link[data-tone="purple"] { color: var(--accent); }

.hr-alert { display: flex; gap: var(--s3); align-items: flex-start; }
.hr-alert-ico {
  display: grid; place-items: center; flex: none;
  width: 32px; height: 32px; border-radius: var(--r-sm);
  background: var(--warning-soft); color: var(--warning);
}
.hr-alert-ico svg { width: 16px; height: 16px; }
.hr-alert-ico[data-sev="alta"] { background: var(--danger-soft); color: var(--danger); }

.hr-ty-ico {
  display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: var(--r-xs);
  background: var(--neutral-soft); color: var(--ink-3);
}
.hr-ty-ico[data-tone="primary"] { background: var(--primary-soft); color: var(--c1); }
.hr-ty-ico[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.hr-ty-ico[data-tone="warning"] { background: var(--warning-soft); color: var(--warning); }
.hr-ty-ico[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.hr-ty-ico[data-tone="accent"]  { background: var(--accent-soft);  color: var(--accent); }
.hr-ty-ico[data-tone="info"]    { background: var(--info-soft);    color: var(--info); }
.hr-ty-ico[data-tone="magenta"] { background: rgba(202, 0, 233, .09); color: var(--c4); }

/* La tabla de solicitudes recientes vive en una columna estrecha: el tipo se
   deja envolver en dos líneas en vez de estirar la tabla y sacar una barra de
   desplazamiento horizontal. */
.hr-req-table td:nth-child(2) { max-width: 130px; }
.hr-req-table td:nth-child(2) span { white-space: normal; line-height: 1.3; }
.hr-req-table td:nth-child(2) .hr-ty-ico { flex: none; }

.hr-quick {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4);
  border: 1px solid var(--border); border-radius: var(--r-md);
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink);
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.hr-quick:hover { border-color: var(--primary); background: var(--primary-soft); color: var(--primary); }
.hr-quick > svg:first-child { color: var(--primary); flex: none; }
.hr-quick > svg:last-child { color: var(--ink-4); flex: none; }

/* --- Mis solicitudes: listado (rediseño 31-ago-2026) --- */
/* Mitades iguales: la lista a la izquierda y el saldo a la derecha (orden de
   Juan del 31-ago-2026). */
.req-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--s5); align-items: start;
}
@media (max-width: 1080px) { .req-grid { grid-template-columns: minmax(0, 1fr); } }

.rq-stat { display: block; text-decoration: none; color: inherit; }
.rq-stat.is-on { border-color: var(--primary); }
.rq-stat-ico {
  display: grid; place-items: center; flex: none;
  width: 42px; height: 42px; border-radius: var(--r-lg);
}
.rq-stat-ico svg { width: 20px; height: 20px; }
.rq-stat-ico[data-tone="blue"]  { background: var(--info-soft); color: var(--info); }
.rq-stat-ico[data-tone="green"] { background: var(--success-soft); color: var(--success); }
.rq-stat-ico[data-tone="amber"] { background: var(--warning-soft); color: var(--warning); }
.rq-stat-ico[data-tone="red"]   { background: var(--danger-soft); color: var(--danger); }
.rq-stat-n {
  font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 700;
  line-height: 1.05; letter-spacing: -.025em;
}
.rq-stat-link {
  display: flex; align-items: center; gap: 4px;
  margin-top: var(--s3); padding-top: var(--s3);
  border-top: 1px solid var(--border-soft);
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink-3);
}
.rq-stat:hover .rq-stat-link { color: var(--primary); }
.rq-stat-link[data-tone="green"] { color: var(--success); }
.rq-stat-link[data-tone="amber"] { color: var(--warning); }
.rq-stat-link[data-tone="red"]   { color: var(--danger); }

.rq-toolbar {
  display: flex; flex-wrap: wrap; gap: var(--s3);
  justify-content: space-between; padding: var(--s4) var(--s5);
}

.rq-list { display: flex; flex-direction: column; gap: var(--s3); padding: 0 var(--s5) var(--s4); }
.rq-row {
  display: flex; align-items: center; gap: var(--s4);
  width: 100%; padding: var(--s4);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface); cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.rq-row:hover { border-color: var(--border-strong); background: var(--surface-2); }
.rq-row-ico {
  display: grid; place-items: center; flex: none;
  width: 46px; height: 46px; border-radius: var(--r-lg);
  background: var(--surface-3); color: var(--ink-2);
}
.rq-row-ico[data-tone="primary"] { background: var(--primary-soft); color: var(--c1); }
.rq-row-ico[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.rq-row-ico[data-tone="warning"] { background: var(--warning-soft); color: var(--warning); }
.rq-row-ico[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.rq-row-ico[data-tone="accent"]  { background: var(--accent-soft);  color: var(--accent); }
.rq-row-ico[data-tone="info"]    { background: var(--info-soft);    color: var(--info); }
.rq-row-ico[data-tone="magenta"] { background: rgba(202, 0, 233, .09); color: var(--c4); }
.rq-row-ico[data-tone="muted"]   { background: var(--neutral-soft);  color: var(--ink-3); }
.rq-row-t { display: block; font-size: var(--fs-base); font-weight: 700; }
.rq-row-d { display: block; margin-top: 2px; font-size: var(--fs-sm); color: var(--ink-2); }
.rq-row-c {
  display: flex; align-items: center; gap: 5px; margin-top: 6px;
  font-size: var(--fs-2xs); color: var(--ink-3);
}
.rq-row-st {
  display: flex; flex-direction: column; align-items: flex-end; gap: 5px;
  flex: none; text-align: right;
}
.rq-row-go { flex: none; color: var(--ink-4); display: grid; place-items: center; }
@media (max-width: 720px) {
  .rq-row { flex-wrap: wrap; }
  .rq-row-st { align-items: flex-start; text-align: left; }
}

.rq-notice { background: var(--info-soft); border-color: transparent; }
.rq-notice-ico { display: grid; place-items: center; color: var(--info); }
.rq-notice-list {
  margin: 0; padding-left: 18px;
  display: flex; flex-direction: column; gap: var(--s2);
  font-size: var(--fs-sm); color: var(--ink-2); line-height: 1.5;
}

/* --- Nueva solicitud: wizard de 3 pasos --- */
.wiz-steps { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s6); flex-wrap: wrap; }
.wiz-step { display: flex; align-items: center; gap: var(--s2); }
.wiz-step .bullet {
  display: grid; place-items: center; flex: none;
  width: 30px; height: 30px; border-radius: 50%;
  font-size: var(--fs-sm); font-weight: 700;
  background: var(--surface); color: var(--ink-3);
  border: 1.5px solid var(--border-strong);
}
.wiz-step .bullet svg { width: 15px; height: 15px; }
.wiz-step.is-current .bullet, .wiz-step.is-done .bullet {
  background: var(--primary); border-color: var(--primary); color: var(--primary-ink);
}
.wiz-step .lb { font-size: var(--fs-sm); font-weight: 600; color: var(--ink-3); }
.wiz-step.is-current .lb { color: var(--primary); }
.wiz-step.is-done .lb { color: var(--ink); }
.wiz-line { width: 72px; height: 1.5px; background: var(--border-strong); opacity: .55; flex: none; }
.wiz-line.is-past { background: var(--primary); opacity: 1; }

.wiz-back-btn { color: var(--primary); }

.req-new-grid {
  display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: var(--s5); align-items: start;
}
@media (max-width: 1080px) { .req-new-grid { grid-template-columns: minmax(0, 1fr); } }

.wiz-q { margin: 0 0 var(--s4); font-size: var(--fs-base); font-weight: 700; }

/* Tarjetas de tipo de solicitud */
.rt-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s3); }
@media (max-width: 640px) { .rt-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.rt-card {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s3); padding: var(--s5) var(--s2); min-height: 104px;
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface); text-align: center; cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.rt-card:hover { border-color: var(--border-strong); background: var(--surface-2); }
.rt-card.is-active { border-color: var(--primary); background: var(--primary-soft); }
.rt-card .rt-name { font-size: var(--fs-xs); font-weight: 600; color: var(--ink-2); line-height: 1.25; }
.rt-card.is-active .rt-name { color: var(--primary); }
.rt-check {
  position: absolute; top: 7px; right: 7px;
  display: grid; place-items: center; width: 17px; height: 17px;
  border-radius: 50%; background: var(--primary); color: var(--primary-ink);
}
.rt-ico { display: grid; place-items: center; color: var(--ink-2); }
.rt-ico[data-tone="primary"] { color: var(--c1); }
.rt-ico[data-tone="success"] { color: var(--c2); }
.rt-ico[data-tone="warning"] { color: var(--c3); }
.rt-ico[data-tone="danger"]  { color: var(--danger); }
.rt-ico[data-tone="accent"]  { color: var(--accent); }
.rt-ico[data-tone="info"]    { color: var(--info); }
.rt-ico[data-tone="magenta"] { color: var(--c4); }
.rt-ico[data-tone="muted"]   { color: var(--ink-2); }

/* Cajas de fecha con rótulo interior */
.date-box {
  display: flex; flex-direction: column; gap: 3px;
  padding: var(--s3) var(--s4);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface); cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.date-box:focus-within { border-color: var(--primary); box-shadow: var(--ring); }
.date-box .dlb { font-size: var(--fs-2xs); color: var(--ink-3); }
.date-box .drow { display: flex; align-items: center; gap: var(--s2); }
.date-box .drow > svg { color: var(--ink-3); flex: none; }
.date-box input[type="date"] {
  border: 0; background: none; padding: 0; margin: 0; width: 100%;
  font: inherit; font-size: var(--fs-md); font-weight: 600; color: var(--ink);
  outline: none;
}
.date-box input[type="date"]::-webkit-calendar-picker-indicator { display: none; }

/* Nota de días hábiles */
.wiz-days {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4); border-radius: var(--r-lg);
  background: var(--primary-soft);
}
.wiz-days > svg { color: var(--primary); flex: none; }
.wiz-days .badge { margin-left: auto; flex: none; }

/* Encabezado de tarjeta con icono de marca */
.h-ico { display: flex; align-items: center; gap: var(--s2); }
.h-ico > svg { color: var(--primary); flex: none; }

/* Filas del resumen */
.sum-row { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) 0; }
.sum-row + .sum-row { border-top: 1px solid var(--border-soft); }
.sum-row .grow { min-width: 0; }
.sum-row .sv { font-size: var(--fs-sm); font-weight: 600; overflow-wrap: anywhere; }
.sum-ico {
  display: grid; place-items: center; flex: none;
  width: 38px; height: 38px; border-radius: var(--r-sm);
  background: var(--surface-3); color: var(--ink-2);
}
.sum-ico svg { width: 18px; height: 18px; }
.sum-ico[data-tone="primary"] { background: var(--primary-soft); color: var(--c1); }
.sum-ico[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.sum-ico[data-tone="warning"] { background: var(--warning-soft); color: var(--warning); }
.sum-ico[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.sum-ico[data-tone="accent"]  { background: var(--accent-soft);  color: var(--accent); }
.sum-ico[data-tone="info"]    { background: var(--info-soft);    color: var(--info); }
.sum-ico[data-tone="magenta"] { background: rgba(202, 0, 233, .09); color: var(--c4); }
.sum-ico[data-tone="muted"]   { background: var(--neutral-soft);  color: var(--ink-3); }

/* Saldo de vacaciones */
.wiz-ring { position: relative; display: grid; place-items: center; flex: none; }
.wiz-ring-c { position: absolute; display: flex; flex-direction: column; align-items: center; gap: 1px; }
.wiz-ring-c b { font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 600; letter-spacing: -.02em; }
.wiz-ring-c b i { font-style: normal; font-size: .58em; color: var(--ink-3); }
.wiz-ring-c > span { font-size: var(--fs-2xs); color: var(--ink-3); }

.bal-row { display: flex; align-items: center; justify-content: space-between; padding: var(--s2) 0; }
.bal-legend {
  display: flex; flex-wrap: wrap; gap: var(--s4);
  margin-top: var(--s4); padding-top: var(--s4);
  border-top: 1px solid var(--border-soft);
}
.bal-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; }

/* ====================================================== ANUNCIOS / FEED = */
.feed-item { display: flex; gap: var(--s3); padding: var(--s3) 0; }
.feed-item + .feed-item { border-top: 1px solid var(--border-soft); }
.feed-ico {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: var(--r-sm);
  background: var(--surface-3); color: var(--ink-3);
}
.feed-ico svg { width: 16px; height: 16px; }

/* Cumpleaños */
.bday {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) 0;
}
.bday .dt {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  flex: none; width: 38px; padding: 4px 0;
  background: var(--surface-3); border-radius: var(--r-xs);
}
.bday .dt .d { font-size: var(--fs-sm); font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.bday .dt .m { font-size: 9px; text-transform: uppercase; color: var(--ink-3); font-weight: 600; letter-spacing: .04em; }
.bday.is-today .dt { background: var(--primary); }
.bday.is-today .dt .d, .bday.is-today .dt .m { color: var(--primary-ink); }

/* ========================================================== AJUSTES === */
.settings-grid { display: grid; grid-template-columns: 232px minmax(0, 1fr); gap: var(--s6); align-items: start; }
@media (max-width: 900px) { .settings-grid { grid-template-columns: minmax(0, 1fr); } }
.settings-nav { display: flex; flex-direction: column; gap: 2px; position: sticky; top: calc(var(--topbar-h) + var(--s5)); }
.settings-nav button {
  display: flex; align-items: center; gap: var(--s3);
  padding: 9px var(--s3); border-radius: var(--r-sm);
  font-size: var(--fs-md); font-weight: 500; color: var(--ink-2); text-align: left;
}
.settings-nav button svg { width: 17px; height: 17px; color: var(--ink-3); }
.settings-nav button:hover { background: var(--surface-3); }
.settings-nav button.is-active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }
.settings-nav button.is-active svg { color: var(--primary); }

.setting-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s5);
  padding: var(--s4) 0; border-bottom: 1px solid var(--border-soft);
}
.setting-row:last-child { border-bottom: 0; }
.setting-row .tt { font-size: var(--fs-md); font-weight: 600; }
.setting-row .ds { font-size: var(--fs-xs); color: var(--ink-3); margin-top: 2px; max-width: 60ch; }

.theme-pick { display: flex; gap: var(--s3); }
.theme-opt {
  flex: 1; padding: var(--s2); border-radius: var(--r-md);
  border: 2px solid var(--border); background: var(--surface);
  transition: all var(--t-fast) var(--ease);
}
.theme-opt:hover { border-color: var(--border-strong); }
.theme-opt.is-active { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.theme-prev {
  height: 62px; border-radius: var(--r-xs); overflow: hidden;
  display: flex; margin-bottom: 7px;
}
.theme-prev .p-side { width: 26%; }
.theme-prev .p-main { flex: 1; padding: 6px; display: flex; flex-direction: column; gap: 4px; }
.theme-prev .p-bar { height: 6px; border-radius: 3px; }
.theme-opt .nm { font-size: var(--fs-xs); font-weight: 600; }

/* ============================================================== VENTAS = */
/* Open Test · Ventas externas (Kajabi y Hotmart).
   Todo cuelga de `.sales-view` a propósito: es la única pantalla con esta
   densidad y estos bloques, y aislarla evita que un ajuste suyo se filtre a
   RRHH o a TI. */

/* ---- Encabezado: estado de la sincronización ---- */
.sync-chip {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: 6px var(--s3) 6px var(--s2);
  border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--border-soft);
}
.sync-ico { display: grid; place-items: center; flex: none; }
.sync-ico[data-tone="success"] { color: var(--success); }
.sync-ico[data-tone="warning"] { color: var(--warning); }
.sync-ico[data-tone="danger"]  { color: var(--danger); }
.sync-lb { font-size: var(--fs-2xs); color: var(--ink-4); line-height: 1.3; }
.sync-vl { font-size: var(--fs-sm); font-weight: 600; color: var(--ink); line-height: 1.3; }

/* ---- Fila superior: salud del negocio + hallazgos ----
   Estas dos tarjetas llevan un rótulo pequeño en vez del encabezado con línea
   de `.card-head`: son bloques de una sola pieza, y el filete horizontal las
   partía en dos secciones que no existen. */
.sales-top { display: grid; gap: var(--s5); grid-template-columns: minmax(0, 300px) minmax(0, 1fr); }
.sales-top > .card { min-width: 0; }
.mini-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s3); margin-bottom: var(--s4);
}
.mini-title {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2);
}
.mini-title svg { color: var(--ink-4); }

.hs-body { display: flex; align-items: center; gap: var(--s4); }

/* La salud vive dentro de la fila de indicadores desde el 11-ago, en el hueco
   que dejó el ingreso neto. Ahí mide una quinta parte del ancho, así que el
   anillo y el badge van juntos en una fila apretada en vez de la composición
   holgada de la franja superior.
 *
 * El contenido arranca justo bajo el rótulo, igual que el número de las tarjetas
 * vecinas. Antes iba con `margin-top:auto` y quedaba pegado al fondo: la tarjeta
 * se leía vacía por arriba y desalineada con las de al lado, que es lo que hacía
 * que «Excelente» y «¿Cómo se calcula?» parecieran caídos. */
.hs-kpi-body { display: flex; align-items: center; gap: var(--s4); padding-top: var(--s1); }
.hs-kpi-body .badge { align-self: flex-start; }
.hs-kpi .hs-ring { flex: none; }
/* El enlace, pegado al badge y sin el interlineado que arrastra por defecto:
   los dos forman un bloque a la altura del centro del anillo. */
.hs-kpi-body .link-btn { text-align: left; line-height: 1.2; }
.hs-ring { position: relative; display: grid; place-items: center; flex: none; }
.hs-num {
  position: absolute;
  font-family: var(--font-display); font-weight: 600; font-size: var(--fs-2xl);
  letter-spacing: -.03em; color: var(--ink); line-height: 1;
}
.hs-num small { font-size: .5em; font-weight: 500; color: var(--ink-4); }
.hs-part { padding: var(--s4) 0; border-bottom: 1px solid var(--border-soft); }
.hs-part:last-child { border-bottom: 0; }

/* Acción dentro de una tarjeta: se lee como enlace y se comporta como botón.
   No es un <a> porque no lleva a ninguna URL — abre algo en esta misma página,
   y un enlace que no navega rompe el clic con el botón central. */
.link-btn {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-sm); font-weight: 600; color: var(--primary);
  padding: 0; background: none; border: 0;
}
.link-btn:hover { color: var(--primary-hover); text-decoration: underline; }
.link-btn svg { width: 15px; height: 15px; }

/* ---- Hallazgos ---- */
.ai-card { position: relative; overflow: hidden; }
/* El botón de la tarjeta toma el violeta de marca y no el azul: es la acción
   del bloque de hallazgos, no una acción de la pantalla. */
.ai-card .btn-soft {
  --btn-bg: var(--accent-soft); --btn-bg-hover: var(--accent-soft);
  --btn-ink: var(--accent); --btn-ink-hover: var(--accent);
}
.ai-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3) var(--s5); }
.ai-list.is-stacked { grid-template-columns: minmax(0, 1fr); }
.ai-item { display: flex; align-items: flex-start; gap: var(--s2); min-width: 0; }
.ai-txt { font-size: var(--fs-sm); color: var(--ink-2); line-height: 1.5; }
.ai-ico {
  display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: var(--r-xs);
  background: var(--neutral-soft); color: var(--ink-3);
}
.ai-ico[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.ai-ico[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.ai-ico[data-tone="warning"] { background: var(--warning-soft); color: var(--warning); }
.ai-ico[data-tone="info"]    { background: var(--info-soft);    color: var(--info); }
.ai-ico[data-tone="accent"]  { background: var(--accent-soft);  color: var(--accent); }
.ai-empty { padding: var(--s2) 0; }
.ai-bot { position: absolute; right: var(--s5); bottom: -8px; pointer-events: none; }
/* Con la ilustración encima, la última fila de texto se metería debajo del
   robot. Se le reserva el sitio en vez de dejar que se solapen. */
@media (min-width: 1100px) { .ai-list { padding-right: 138px; } }
@media (max-width: 1099px) { .ai-bot { display: none; } }

/* ---- Indicadores ---- */
.skpi-row {
  display: grid; gap: var(--s5); margin-bottom: var(--s5);
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
.skpi { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s4) var(--s5) var(--s3); }
.skpi-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s3); }
.skpi-label { font-size: var(--fs-sm); font-weight: 500; color: var(--ink-3); }
.skpi-value {
  font-family: var(--font-display);
  font-size: var(--fs-2xl); font-weight: 600; line-height: 1.05;
  letter-spacing: -.028em; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.skpi-value .unit { font-size: var(--fs-lg); font-weight: 500; color: var(--ink-3); margin-left: 2px; }
.skpi-foot { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--s3); }
.skpi-delta {
  display: inline-flex; align-items: center; gap: 3px; align-self: flex-start;
  padding: 2px 8px; border-radius: var(--r-full);
  font-size: var(--fs-2xs); font-weight: 700; font-variant-numeric: tabular-nums;
  background: var(--neutral-soft); color: var(--ink-3);
}
.skpi-delta[data-tone="good"] { background: var(--success-soft); color: var(--success); }
.skpi-delta[data-tone="bad"]  { background: var(--danger-soft);  color: var(--danger); }
.skpi-delta svg { width: 12px; height: 12px; }
.skpi-note { font-size: var(--fs-2xs); color: var(--ink-4); white-space: nowrap; }
.skpi-trend { flex: 1 1 0; min-width: 0; max-width: 132px; }

/* Tonos que faltaban en las tarjetas de indicador */
.stat-ico[data-tone="primary"] { background: var(--primary-soft); color: var(--primary); }
.stat-ico[data-tone="info"]    { background: var(--info-soft);    color: var(--info); }

/* ---- Barra de filtros ---- */
.sales-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3);
  margin-bottom: var(--s5);
}
.fsel {
  position: relative; display: flex; flex-direction: column; justify-content: center;
  min-width: 150px; height: 52px; padding: 0 var(--s4) 0 var(--s3);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.fsel:hover { border-color: var(--border-strong); }
.fsel:focus-within { border-color: var(--primary); box-shadow: var(--ring); }
.fsel-lb { font-size: var(--fs-2xs); color: var(--ink-4); line-height: 1.2; padding-left: 3px; }
.fsel select {
  appearance: none; -webkit-appearance: none;
  width: 100%; height: 22px; padding: 0 var(--s5) 0 3px;
  /* Mismo arreglo que `.select`: con `appearance: none` Chrome pinta el texto
     a la altura de la línea en vez de centrarlo; la línea mide lo que mide el
     control y el texto queda en su sitio. */
  line-height: 22px;
  background: none; border: 0; outline: none; cursor: pointer;
  font-size: var(--fs-md); font-weight: 600; color: var(--ink);
  text-overflow: ellipsis;
}
/* Un desplegable deshabilitado no se atenúa: no está roto ni prohibido, y el
   porqué está en su título. Atenuarlo se leería como «esto falló». */
.fsel select:disabled { cursor: default; color: var(--ink-2); opacity: 1; }
.fsel > svg { position: absolute; right: var(--s3); bottom: 15px; color: var(--ink-4); pointer-events: none; }

/* Aquí vivía `.fsel-search`, el buscador dentro de la barra de filtros de
   Clientes. Se retiró el 26-ago: la búsqueda se movió a `.table-search`,
   pegada a la tabla, que es donde se busca de verdad. */

/* ---- Buscador pegado a la tabla ----
   Vive DENTRO de la tarjeta, justo encima del encabezado (pedido de Juan,
   26-ago): se busca mirando las filas, no la barra de filtros. El borde
   inferior lo separa del thead sin encajonarlo en otra caja. */
.table-search {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--border);
}
.table-search > svg { color: var(--ink-4); flex: 0 0 auto; }
.table-search input[type="search"] {
  flex: 1 1 auto; min-width: 0; height: 24px;
  background: none; border: 0; outline: none;
  font-family: inherit; font-size: var(--fs-sm); font-weight: 500; color: var(--ink);
}
.table-search input::placeholder { color: var(--ink-4); }

/* --------------------------------------------- Ficha de una transacción --
   La hoja que se abre al pulsar una fila de Transacciones, con la forma que
   dejó el diseñador (Juan, 15-sep-2026: «que sea igual, tal cual»). Dos
   columnas: pestañas a la izquierda, estado / producto / comprador a la
   derecha.

   NO LLEVA `modal-head` NI `modal-foot`. La cabecera es propia —icono, rótulo,
   título y referencia— y abajo no hay botonera: los dos botones que dibujó el
   boceto («Descargar comprobante» y «Compartir detalles») los quitó Juan en el
   mismo mensaje. Por eso el cuerpo del modal se queda sin relleno y la hoja lo
   reparte por zonas.

   LA CABECERA NO SE VA CON EL SCROLL: la hoja es una columna flexible y lo
   único que desplaza es `.tx-cols`. En un modal de 88vh con cuatro pestañas,
   perder de vista de qué venta se está hablando al bajar es justo lo que hace
   que alguien cuadre la venta equivocada.

   Los colores salen todos de tokens y ninguno está escrito a mano: la ficha
   tiene que verse igual de bien en claro y en oscuro, y el boceto llegó solo
   en claro. */
.modal-body:has(.tx-sheet) { padding: 0; overflow: hidden; display: flex; }
.tx-sheet {
  display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0;
  /* Borde izquierdo de la hoja + icono + separación: donde empieza el título. */
  --tx-sangria: calc(var(--s5) + 48px + var(--s4));
}

.tx-head {
  display: flex; align-items: flex-start; gap: var(--s4);
  padding: var(--s5) var(--s5) var(--s4);
}
.tx-ico {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 48px; height: 48px; border-radius: var(--r-md);
  background: var(--primary-soft); color: var(--primary);
}
.tx-kicker {
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-4);
}
.tx-title {
  margin: 3px 0 0;
  font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 600;
  letter-spacing: -.02em; line-height: 1.25;
}
.tx-ref { margin-top: var(--s2); font-size: var(--fs-xs); color: var(--ink-3); }
.tx-ref-order { color: var(--ink-4); }

.tx-chips {
  display: flex; flex-wrap: wrap; gap: var(--s2);
  padding: 0 var(--s5) var(--s4) var(--tx-sangria);
}
/* LAS ETIQUETAS ARRANCAN DONDE ARRANCA EL TÍTULO, no en el borde de la hoja
   (Juan, 15-sep-2026: «los tags de tienda, status y eso, que se corran a la
   derecha para que se alineen con el texto»). El sangrado es el ancho del
   icono más su separación, escrito como variable en un solo sitio: si el
   icono cambia de tamaño, la alineación lo sigue sola en vez de quedarse
   descuadrada con un número copiado.

   Por debajo de 640 px vuelven al borde: a lo ancho de un teléfono, sangrar
   68 de 375 px para alinear tres etiquetas las parte en más renglones de los
   que ahorra, y ahí el ancho vale más que la alineación. */
.tx-dot {
  width: 7px; height: 7px; border-radius: var(--r-full);
  background: currentColor; flex: 0 0 auto;
}

.tx-cols {
  display: grid; grid-template-columns: minmax(0, 1fr) 328px;
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  border-top: 1px solid var(--border-soft);
}
.tx-main { min-width: 0; padding: var(--s4) var(--s5) var(--s5); }
.tx-side {
  display: flex; flex-direction: column; gap: var(--s4);
  padding: var(--s5);
  background: var(--surface-2); border-left: 1px solid var(--border-soft);
}

/* Las pestañas son las de la casa (`.tabs`), no unas propias: el subrayado y
   el color activo ya existen y el boceto dibuja exactamente eso. */
.tx-tabs { margin-bottom: var(--s4); }
.tx-pane { display: none; }
.tx-pane.is-on { display: block; }

.tx-sec {
  margin: 0 0 var(--s3);
  font-size: var(--fs-md); font-weight: 600; letter-spacing: -.01em;
}
.tx-sec + .tx-grid + .tx-sec,
.tx-grid + .tx-sec,
.alert + .tx-sec { margin-top: var(--s5); }

/* ---- Ventas de Stripe de Renovaciones (0128) ----
   El formulario de «+ Stripe»: dos bloques con su rótulo —el cliente y el
   pago— y el neto calculado a la vista, con el aspecto de un campo pero sin
   serlo: se lee, no se escribe. */
.st-sec {
  display: flex; align-items: center; gap: var(--s2);
  margin: var(--s2) 0 0; padding-top: var(--s3); border-top: 1px solid var(--border);
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2);
}
.st-sec:first-of-type { border-top: 0; padding-top: 0; }
.st-sec svg { color: var(--primary); }
.st-neto {
  display: flex; align-items: center; height: 40px; padding: 0 var(--s3);
  border-radius: var(--r-md); background: var(--surface-2);
  font-weight: 600; color: var(--ink);
}
.st-neto.is-bad { color: var(--danger); }
[data-stripe-slot] .btn-danger { margin-top: var(--s4); }

.tx-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.tx-dato {
  display: flex; align-items: center; gap: var(--s3); min-width: 0;
  padding: var(--s3) var(--s4);
  background: var(--surface-2);
  border: 1px solid var(--border-soft); border-radius: var(--r-md);
}
.tx-dato.is-wide { grid-column: 1 / -1; }
.tx-dato-ico {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 32px; height: 32px; border-radius: var(--r-sm);
  background: var(--surface); border: 1px solid var(--border-soft);
  color: var(--ink-3);
}
.tx-dato-lb { display: block; font-size: var(--fs-2xs); color: var(--ink-4); line-height: 1.3; }
.tx-dato-vl {
  display: block; margin-top: 2px;
  font-size: var(--fs-md); font-weight: 600; color: var(--ink);
  line-height: 1.35; overflow-wrap: anywhere;
}
/* La referencia ocupa la fila entera y su botón de copiar se va al extremo. */
.tx-dato.is-wide .tx-dato-vl { display: flex; align-items: center; gap: var(--s2); }
.tx-copiable { overflow-wrap: anywhere; }
.tx-copy { margin-left: auto; flex: 0 0 auto; }

.tx-items {
  display: flex; flex-direction: column; gap: var(--s2);
  padding: var(--s3) var(--s4);
  background: var(--surface-2);
  border: 1px solid var(--border-soft); border-radius: var(--r-md);
}

/* --- La columna derecha --- */

.tx-card {
  padding: var(--s4);
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-md);
}
.tx-card-k {
  margin-bottom: var(--s3);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-4);
}
.tx-prod { display: flex; align-items: center; gap: var(--s3); }
.tx-prod-img {
  flex: 0 0 auto; display: grid; place-items: center; overflow: hidden;
  width: 44px; height: 44px; border-radius: var(--r-sm);
  background: var(--surface-3); color: var(--ink-3);
  font-weight: 700; font-size: var(--fs-lg);
}
.tx-prod-img img { width: 100%; height: 100%; object-fit: cover; }
.tx-prod-name { font-size: var(--fs-sm); font-weight: 600; line-height: 1.35; }

.tx-filas {
  display: flex; flex-direction: column; gap: var(--s2);
  margin-top: var(--s3); padding-top: var(--s3);
  border-top: 1px solid var(--border-soft);
}
.tx-fila { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); }
.tx-fila .lb { flex: 0 0 auto; font-size: var(--fs-xs); color: var(--ink-4); }
.tx-fila .vl {
  min-width: 0; text-align: right;
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink);
  overflow-wrap: anywhere;
}

.tx-buyer { display: flex; align-items: center; gap: var(--s3); min-width: 0; }
.tx-buyer-ico {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 34px; height: 34px; border-radius: var(--r-full);
  background: var(--surface-3); color: var(--ink-3);
}
.tx-buyer-n { font-size: var(--fs-sm); font-weight: 600; overflow-wrap: anywhere; }
.tx-buyer .t-xs { overflow-wrap: anywhere; }
.tx-verperfil { width: 100%; margin-top: var(--s3); justify-content: center; }

/* El historial no es un registro de auditoría —`sales` no lo tiene— sino los
   tres instantes que la casa guarda de una venta. Se lee de arriba abajo en el
   orden en que pasaron. */
.tx-time { list-style: none; margin: 0; padding: 0; }
.tx-time li {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3) 0; border-bottom: 1px solid var(--border-soft);
}
.tx-time li:last-child { border-bottom: 0; }
.tx-time-ico {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: var(--r-full);
  background: var(--surface-3); color: var(--ink-3);
}
.tx-time-ico[data-tone="ok"]   { background: var(--success-soft); color: var(--success); }
.tx-time-ico[data-tone="warn"] { background: var(--warning-soft); color: var(--warning); }
.tx-time-ico[data-tone="bad"]  { background: var(--danger-soft);  color: var(--danger); }
.tx-time-t { font-size: var(--fs-sm); font-weight: 600; }
.tx-time-at { flex: 0 0 auto; margin-left: auto; white-space: nowrap; }

/* --- Insignia digital (BadgeClaimed, 28-sep-2026) ---
   En la tabla: palomita verde si se emitió, X gris si no, X roja si falló, y
   un guion donde no aplica (venta sin cobrar). El gris y no el rojo para
   «sin emitir» es a propósito: una columna entera de X rojas se lee como una
   pantalla llena de errores, y no emitir todavía no es un error. */
.bdg-th, .bdg-td { width: 1%; white-space: nowrap; }
.bdg-cell { display: inline-grid; place-items: center; vertical-align: middle; }
.bdg-cell.is-ok  { color: var(--success); }
.bdg-cell.is-no  { color: var(--ink-4); }
.bdg-cell.is-bad { color: var(--danger); }
.bdg-cell.is-wait-ico { color: var(--warning); }
.bdg-cell.is-na  { color: var(--ink-4); }
.bdg-cell.is-wait {
  width: 19px; height: 19px; border-radius: var(--r-full);
  background: var(--surface-3);
}

.bdg-state {
  display: flex; align-items: center; gap: var(--s2);
  font-size: var(--fs-sm); font-weight: 700;
}
.bdg-state.is-ok  { color: var(--success); }
.bdg-state.is-no  { color: var(--ink-3); }
.bdg-state.is-bad { color: var(--danger); }
.bdg-state.is-wait-ico { color: var(--warning); }
.bdg-note { margin-top: var(--s2); }
.bdg-err { margin-top: var(--s2); color: var(--danger); overflow-wrap: anywhere; }
.bdg-btn { width: 100%; margin-top: var(--s3); justify-content: center; }
.bdg-confirm {
  margin-top: var(--s3); padding: var(--s2) var(--s3);
  background: var(--warning-soft); color: var(--ink-2);
  border-radius: var(--r-sm);
}
.bdg-pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); margin-top: var(--s2); }
.bdg-pair .btn { justify-content: center; }
.bdg-alert { margin-top: var(--s3); }
.bdg-alert[hidden] { display: none; }

/* ------------------------------------------------ Ficha de un cliente ----
   La hoja que se abre al pulsar una fila de Clientes, con la forma del
   diseñador (Juan, 15-sep-2026: «el modal de cliente quiero que sea así»).

   COMPARTE PIEZAS CON LA FICHA DE UNA TRANSACCIÓN, y no por ahorrar: son dos
   hojas de la misma familia y el usuario salta de una a otra pulsando una
   compra. Las pestañas (`.tabs`), los paneles (`.tx-pane`), las celdas de dato
   (`.tx-grid` / `.tx-dato`) y el punto de las etiquetas (`.tx-dot`) son los
   mismos; lo propio de aquí es la cabecera con avatar, las cuatro cifras y la
   banda de cierre de la tabla.

   Esta sí lleva `modal-foot` —la de transacción no— porque el boceto pone tres
   botones abajo y los tres hacen algo. */
/* `min-width: 0` en la hoja y en el cuerpo, y no es adorno: un hijo de flex
   nace con `min-width: auto`, que es el ancho MÍNIMO DE SU CONTENIDO, y el
   contenido aquí es una tabla de ocho columnas. Sin esto la hoja se estira a
   lo que mide la tabla —652 px medidos en un móvil de 375— y `.modal`, que
   recorta, se come la mitad derecha sin dejar forma de llegar a ella. Con
   ello, la tabla vuelve a desplazarse dentro de su `.table-wrap`, que es
   justo para lo que está. */
.modal-body:has(.cu-sheet) { padding: 0; overflow: hidden; display: flex; }
.cu-sheet {
  display: flex; flex-direction: column; flex: 1 1 auto;
  min-height: 0; min-width: 0;
}

.cu-head {
  display: flex; align-items: flex-start; gap: var(--s4);
  padding: var(--s5) var(--s5) var(--s4);
  border-bottom: 1px solid var(--border-soft);
}
/* El avatar de la ficha: las iniciales del nombre, en grande. La lista tuvo
   uno pequeño (`.cu-ini`) hasta el 22-sep-2026, cuando Juan lo quitó por
   poco usable; en la ficha se queda. */
.cu-avatar {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 62px; height: 62px; border-radius: var(--r-full);
  background: var(--primary-soft); color: var(--primary);
  font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 700;
  letter-spacing: .02em;
}
.cu-name {
  margin: 0;
  font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 600;
  letter-spacing: -.02em; line-height: 1.2; overflow-wrap: anywhere;
}
.cu-sub { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); margin-top: var(--s2); }
.cu-ref { font-size: var(--fs-sm); font-weight: 600; color: var(--ink-3); }
/* Los tres datos de contacto en una fila, con su icono. Se parten en varias
   líneas antes que recortar un correo: el correo es para copiarlo. */
.cu-meta {
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5);
  margin-top: var(--s3);
  font-size: var(--fs-sm); color: var(--ink-2);
}
.cu-meta > span { display: inline-flex; align-items: center; gap: var(--s2); min-width: 0; }
.cu-meta svg { width: 15px; height: 15px; color: var(--ink-4); flex: 0 0 auto; }
.cu-meta [data-cu-mail] { overflow-wrap: anywhere; }

.cu-body { flex: 1 1 auto; min-height: 0; min-width: 0; overflow-y: auto; padding: var(--s5); }
.cu-panes { min-width: 0; }

.cu-kpis {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s3);
  margin-bottom: var(--s5);
}
.cu-kpi {
  display: flex; align-items: flex-start; gap: var(--s3); min-width: 0;
  padding: var(--s4);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
}
/* Los tonos son los de `.stat-ico`, para que una cifra se vea igual aquí que
   en cualquier panel de la casa. */
.cu-kpi-ico {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 38px; height: 38px; border-radius: var(--r-sm);
  background: var(--primary-soft); color: var(--primary);
}
.cu-kpi-ico[data-tone="success"], .cu-kpi-ico[data-tone="teal"] { background: var(--success-soft); color: var(--success); }
.cu-kpi-ico[data-tone="purple"], .cu-kpi-ico[data-tone="accent"] { background: var(--accent-soft); color: var(--accent); }
.cu-kpi-ico[data-tone="amber"] { background: var(--warning-soft); color: var(--warning); }
.cu-kpi-lb { display: block; font-size: var(--fs-xs); color: var(--ink-3); line-height: 1.3; }
.cu-kpi-vl {
  display: block; margin: 2px 0 1px;
  font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 600;
  letter-spacing: -.02em; line-height: 1.15; overflow-wrap: anywhere;
}
.cu-kpi-ft { display: block; font-size: var(--fs-2xs); color: var(--ink-4); line-height: 1.3; }

.cu-tabs { margin-bottom: var(--s4); }
.cu-pane-head { display: flex; align-items: flex-start; gap: var(--s3); margin-bottom: var(--s3); }
.cu-sec { margin: 0; font-size: var(--fs-md); font-weight: 600; letter-spacing: -.01em; }

/* La banda que cierra la tabla de compras. Tres cifras separadas por una
   línea, sobre fondo teñido: es un cierre de tabla, no una tarjeta más, y por
   eso no lleva borde completo. */
.cu-resumen {
  display: flex; align-items: center; gap: var(--s4);
  margin-top: var(--s4); padding: var(--s4);
  background: var(--primary-soft); border-radius: var(--r-md);
}
.cu-resumen-ico {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 38px; height: 38px; border-radius: var(--r-full);
  background: var(--surface); color: var(--primary);
}
.cu-resumen-d { flex: 1 1 0; min-width: 0; padding-left: var(--s4); border-left: 1px solid var(--border); }
.cu-resumen-d:first-of-type { border-left: 0; padding-left: 0; }
.cu-resumen-d .lb { display: block; font-size: var(--fs-2xs); color: var(--ink-3); }
.cu-resumen-d .vl {
  display: block; margin-top: 1px;
  font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 600;
  letter-spacing: -.02em; overflow-wrap: anywhere;
}

/* ---- La ficha como página (22-sep-2026) ----
   Era un modal y ahora es una página con dirección propia: la tarjeta crece
   con su contenido y la que se desplaza es la página, no una caja dentro de
   otra (Juan: «hacer scroll es feo»). Los botones que el modal tenía abajo
   van a la derecha de la cabecera. */
.cu-crumb { margin-bottom: var(--s4); }
/* «← Clientes», grande y en azul: tiene que verse que se puede pulsar. A 12 px
   y en gris pasaba por texto (Juan, 22-sep-2026). Solo aquí; el resto de
   `.crumb-back` sigue igual. */
.cu-crumb .crumb-back {
  gap: var(--s2); padding: 6px 12px 6px 8px; margin-left: -8px;
  font-size: var(--fs-lg); font-weight: 600; color: var(--primary);
  border-radius: var(--r-md);
  transition: background .15s ease;
}
.cu-crumb .crumb-back svg { width: 20px; height: 20px; }
.cu-crumb .crumb-back:hover { background: var(--primary-soft); color: var(--primary); }
.cu-page { overflow: hidden; }
.cu-page .cu-body { overflow: visible; }
.cu-actions { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2); flex: none; }
.cu-actions [data-cu-mailslot]:empty { display: none; }

/* Cuatro cifras caben mientras el modal tenga sus 1040 px; por debajo van de
   dos en dos, y en el teléfono la banda de cierre se apila. */
@media (max-width: 900px) {
  .cu-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .cu-page .cu-head { flex-wrap: wrap; }
  .cu-page .cu-actions { width: 100%; }
  .cu-page .cu-actions .btn { flex: 1 1 auto; justify-content: center; }
  .cu-head { padding: var(--s4) var(--s4) var(--s3); gap: var(--s3); }
  .cu-avatar { width: 48px; height: 48px; font-size: var(--fs-lg); }
  .cu-name { font-size: var(--fs-xl); }
  .cu-body { padding: var(--s4); }
  .cu-kpis { grid-template-columns: minmax(0, 1fr); }
  .cu-resumen { flex-wrap: wrap; gap: var(--s3); }
  .cu-resumen-d { flex: 1 1 100%; padding-left: 0; border-left: 0; }
}

/* Dos columnas caben mientras el modal mida sus 1040 px. Por debajo, la
   columna de la derecha pasa DEBAJO y no se encoge: el boceto la dibujó a 328
   px y a menos de eso la ficha del producto parte el nombre en cuatro
   renglones. El corte va aquí, con el componente, y no en `mobile.css`: no
   depende del ancho de la pantalla sino del ancho que el modal consiguió. */
@media (max-width: 1000px) {
  .tx-cols { grid-template-columns: minmax(0, 1fr); }
  .tx-side { border-left: 0; border-top: 1px solid var(--border-soft); }
}
@media (max-width: 640px) {
  .tx-head { padding: var(--s4) var(--s4) var(--s3); gap: var(--s3); }
  .tx-ico { width: 40px; height: 40px; }
  .tx-title { font-size: var(--fs-lg); }
  .tx-chips { padding: 0 var(--s4) var(--s3); }   /* al borde: ver la nota de arriba */
  .tx-main, .tx-side { padding: var(--s4); }
  .tx-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   Service Desk
   Estructura de mesa de ayuda: rail de vistas guardadas con contador, lista
   densa y ficha con la conversación. El color de marca solo en lo accionable
   —la vista activa y el botón de responder—; la prioridad va en una barra de
   3 px, que informa sin pintar la fila entera de rojo.
   ========================================================================== */
.sd-shell { display: grid; grid-template-columns: 208px minmax(0, 1fr); gap: var(--s5); align-items: start; }

.sd-rail { position: sticky; top: calc(var(--topbar-h) + var(--s5)); display: flex; flex-direction: column; gap: 2px; }
.sd-rail-h {
  padding: var(--s2) var(--s3) 6px;
  font-size: var(--fs-3xs); font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-4);
}
.sd-view {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s2);
  padding: 8px var(--s3); border-radius: var(--r-sm);
  font-size: var(--fs-md); color: var(--ink); text-decoration: none;
  transition: background var(--t-fast) var(--ease);
}
.sd-view:hover { background: var(--primary-soft); text-decoration: none; }
.sd-view.is-active { background: var(--primary); color: var(--primary-ink); font-weight: 600; }
.sd-view .lb { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-view .n {
  flex: none; font-size: var(--fs-2xs); font-weight: 700; font-variant-numeric: tabular-nums;
  padding: 1px 7px; border-radius: var(--r-full);
  background: var(--surface-3); color: var(--ink-3);
}
.sd-view.is-active .n { background: rgba(255, 255, 255, .22); color: var(--primary-ink); }
[data-theme="dark"] .sd-view.is-active .n { background: rgba(10, 15, 31, .2); }
.sd-view .n.is-alert { background: var(--danger); color: #fff; }

.sd-list { overflow: hidden; }
.sd-row {
  display: flex; align-items: center; gap: var(--s3);
  width: 100%; padding: var(--s3) var(--s4); text-align: left;
  border-bottom: 1px solid var(--border-soft);
  transition: background var(--t-fast) var(--ease);
}
.sd-row:last-child { border-bottom: 0; }
.sd-row:hover { background: var(--surface-2); }
.sd-row .prio { flex: none; width: 3px; align-self: stretch; border-radius: 2px; }
.sd-row .main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.sd-row .subj {
  font-size: var(--fs-md); font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sd-row .meta {
  font-size: var(--fs-2xs); color: var(--ink-4);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sd-row .age {
  flex: none; min-width: 44px; text-align: right;
  font-size: var(--fs-xs); color: var(--ink-4); font-variant-numeric: tabular-nums;
}
/* Un ticket fuera de SLA se marca en el borde, no llenando la fila de color:
   si veinte filas gritan, ninguna se lee. */
.sd-row.is-late { box-shadow: inset 3px 0 0 var(--danger); }
.sd-row .age.is-late { color: var(--danger); font-weight: 700; }
.sd-unassigned {
  display: grid; place-items: center; flex: none; width: 30px; height: 30px;
  border-radius: var(--r-full); background: var(--surface-3); color: var(--ink-4);
  border: 1px dashed var(--border-strong);
}

/* ---- Ficha: conversación + propiedades ---- */
.sd-detail { display: grid; grid-template-columns: minmax(0, 1fr) 232px; gap: var(--s5); align-items: start; }
.sd-thread { display: flex; flex-direction: column; gap: var(--s3); min-width: 0; }
.sd-msg { padding: var(--s3) var(--s4); border-radius: var(--r-md); background: var(--surface-2); }
.sd-msg .who {
  display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2); margin-bottom: 4px;
}
.sd-msg .tx { font-size: var(--fs-md); color: var(--ink); white-space: pre-wrap; }
/* Quien escribe de fuera, quien contesta desde dentro y la nota que el cliente
   nunca ve tienen que distinguirse sin leer: son tres cosas distintas. */
.sd-msg.is-in  { background: var(--surface-3); }
.sd-msg.is-out { background: var(--primary-soft); border-left: 2px solid var(--primary); }
.sd-msg.is-note { background: var(--warning-soft); border-left: 2px solid var(--warning); }
.sd-props { min-width: 0; }
@media (max-width: 860px) {
  .sd-shell, .sd-detail { grid-template-columns: minmax(0, 1fr); }
  .sd-rail { position: static; }
}

/* ---- Parrilla de contenidos ----
   Siete columnas de igual ancho. En móvil se apilan: una semana en horizontal
   a 360 px daría columnas de 45 px, donde no cabe ni el nombre del canal. */
.mkt-week {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--s2);
}
.mkt-day {
  display: flex; flex-direction: column; gap: var(--s2);
  min-height: 148px; padding: var(--s2);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
}
.mkt-day.is-today { border-color: var(--primary); }
.mkt-day-h { display: flex; align-items: baseline; gap: 5px; }
.mkt-day-h .d { font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 700; }
.mkt-day-h .w { font-size: var(--fs-2xs); color: var(--ink-4); text-transform: uppercase; }
.mkt-day .mkt-empty { color: var(--ink-4); font-size: var(--fs-xs); }
.mkt-post {
  display: flex; flex-direction: column; gap: 3px; width: 100%;
  padding: 6px 7px; text-align: left;
  background: var(--primary-soft); border-radius: var(--r-xs);
}
.mkt-post:hover { background: var(--primary-soft-2); }
.mkt-post[data-tone="success"] { background: var(--success-soft); border-left-color: var(--success); }
.mkt-post[data-tone="amber"]   { background: var(--warning-soft); border-left-color: var(--warning); }
.mkt-post[data-tone="muted"]   { background: var(--surface-3); border-left-color: var(--border-strong); }
.mkt-post .ch {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-3xs); font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--ink-3);
}
.mkt-post .tt {
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink); line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3;
  -webkit-box-orient: vertical; overflow: hidden;
}
.mkt-row { width: 100%; padding: var(--s2) var(--s3); border-radius: var(--r-xs); text-align: left; }
.mkt-row:hover { background: var(--surface-2); }
@media (max-width: 900px) {
  .mkt-week { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .mkt-week { grid-template-columns: minmax(0, 1fr); }
  .mkt-day { min-height: 0; }
}

/* ---- Clientes ----
   La lista con los bocetos de Juan (22-sep-2026). Arriba, el título y a su
   lado cuántos clientes hay en lo que se está viendo; debajo, la barra de
   filtros en una tarjeta blanca; y la tabla, una línea por cliente. Las
   cuatro tarjetas de indicadores que había encima se
   quitaron el mismo día, también a pedido, y después el círculo de
   iniciales y el ID de cada fila (siguen en la ficha del cliente). */

/* Cuántos clientes hay en el periodo, con los filtros puestos, al lado del
   título (Juan: «al lado del título quiero que salga cuántos clientes hay con
   respecto a la franja de tiempo que está visualizando»). Antes encabezaba
   la tabla. */
.cu-count {
  display: inline-flex; align-items: center; height: 28px; padding: 0 12px;
  background: var(--primary-soft); color: var(--ink);
  border-radius: var(--r-full);
  font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.cu-note {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); color: var(--ink-3);
}

/* ---- La barra de filtros de Clientes ----
   Juan, 22-sep-2026, con un boceto: «quiero que la barra de acciones sea así
   tal cual, pero donde dice limpiar filtros ahí va el botón de exportar».
   Reemplaza a los filtros en el marino del raíl que había pedido esa misma
   tarde. Una tarjeta blanca; dentro, el buscador en gris claro y cada
   desplegable con su rótulo ENCIMA de la caja, no dentro. Todo se alinea por
   abajo, a 40 px. Solo aquí: Ventas y Transacciones siguen con su barra. */
.cu-bar {
  align-items: flex-end; gap: var(--s3);
  padding: var(--s3) var(--s4);
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
}

.cu-search {
  display: flex; align-items: center; gap: var(--s2);
  flex: 1 1 280px; min-width: 220px; max-width: 420px; height: 40px;
  padding: 0 var(--s3);
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md);
  color: var(--ink-4); cursor: text;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.cu-search:hover { border-color: var(--border-strong); }
.cu-search:focus-within {
  border-color: var(--primary); box-shadow: var(--ring);
  background: var(--surface); color: var(--primary);
}
.cu-search > svg { flex: none; }
.cu-search input {
  flex: 1 1 auto; min-width: 0; height: 100%;
  background: none; border: 0; outline: none;
  font-family: inherit; font-size: var(--fs-md); color: var(--ink);
}
.cu-search input::placeholder { color: var(--ink-4); }

/* El desplegable: `.fsel` deja de ser la caja y pasa a ser la columna
   «rótulo encima + caja»; la caja es el propio <select>, o el campo de
   fecha del periodo personalizado. */
.cu-bar .fsel {
  height: auto; min-width: 120px; padding: 0; gap: 6px;
  justify-content: flex-end;
  background: none; border: 0; box-shadow: none; cursor: default;
}
.cu-bar .fsel.fsel-date { min-width: 150px; }
.cu-bar .fsel:hover,
.cu-bar .fsel:focus-within { border: 0; box-shadow: none; }
.cu-bar .fsel-lb {
  padding-left: 2px; line-height: 1;
  font-size: var(--fs-xs); font-weight: 500; color: var(--ink-3);
}
.cu-bar .fsel select,
.cu-bar .fsel.fsel-date input[type="date"] {
  width: 100%; height: 40px; padding: 0 34px 0 12px; line-height: 38px;
  background-color: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-md);
  font-size: var(--fs-md); font-weight: 500; color: var(--ink);
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.cu-bar .fsel select:hover,
.cu-bar .fsel.fsel-date input[type="date"]:hover { border-color: var(--border-strong); }
.cu-bar .fsel select:focus-visible,
.cu-bar .fsel.fsel-date input[type="date"]:focus-visible {
  border-color: var(--primary); box-shadow: var(--ring); outline: none;
}
.cu-bar .fsel > svg { right: 12px; bottom: 12px; color: var(--ink-3); }
.cu-bar .fsel.fsel-date input[type="date"] { padding-right: 32px; background-position: right 12px center; }

/* Exportar, donde el boceto pone «Limpiar filtros»: al final y a la altura de
   las cajas. `margin-left: auto` lo deja a la derecha también cuando la barra
   no cabe y baja a otra línea. */
.cu-bar-end { display: flex; align-items: flex-end; gap: var(--s3); margin-left: auto; }
.cu-bar .cu-export { height: 40px; padding: 0 var(--s4); border-radius: var(--r-md); }

/* Nombre, país y correo son las columnas que ceden: con `max-width: 0` la
   celda deja de exigir el ancho de su texto entero, se reparte el que sobra
   y lo largo termina en «…» (el completo va en el `title`). Sin esto, con
   siete columnas la tabla se salía 156 px de la tarjeta en un portátil de
   1366. Solo con eso, en cambio, las tres se quedaban en 90 px y el sobrante
   se lo llevaba Plataforma: el porcentaje de la cabecera les guarda su parte.
   En teléfono no aplica: la tabla apilada pone `max-width: none`. */
.cu-table td.cu-fluid { max-width: 0; }
.cu-table .t-clip { min-width: 0; }
.cu-table .cu-w-cli  { width: 26%; }
.cu-table .cu-w-pais { width: 13%; }
.cu-table .cu-w-mail { width: 22%; }
.cu-table.cu-sin-pii .cu-w-cli  { width: 32%; }
.cu-table.cu-sin-pii .cu-w-pais { width: 16%; }

/* Una línea por fila: solo el nombre, sin círculo ni ID debajo (Juan,
   22-sep-2026), y un poco menos de aire arriba y abajo que el resto de
   tablas, para que la lista sea más baja. */
.cu-table tbody td { padding-top: 10px; padding-bottom: 10px; }
.cu-nm {
  display: block;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-md); font-weight: 600; color: var(--ink);
}
.cu-mail {
  display: block;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ink-2);
}
.cu-skel { display: inline-block; height: 10px; border-radius: var(--r-full); vertical-align: middle; }

/* Las plataformas del cliente, cada una con su logo (`.src-chip`, en
   components.css). Los chips no se parten en dos líneas: la fila tiene que
   medir lo mismo que las demás (Juan pidió la tabla más baja). Si alguien
   compró en las tres tiendas, la columna se ensancha y ceden nombre, país y
   correo, que son las fluidas. */
.cu-srcs { display: flex; flex-wrap: nowrap; gap: 4px; }
.cu-reemb { font-size: var(--fs-2xs); color: var(--danger); }
.cu-fecha { color: var(--ink-3); }

/* Las cabeceras que ordenan: el doble galón dice «se puede», la flecha en
   azul dice cuál manda y hacia dónde. */
.th-sort { display: inline-flex; align-items: center; gap: 4px; color: inherit; }
.th-sort svg { opacity: .5; flex: none; }
.th-sort:hover { color: var(--ink); }
.table thead th.is-sorted .th-sort { color: var(--ink); }
.table thead th.is-sorted .th-sort svg { opacity: 1; color: var(--primary); }
/* Como en el boceto de la tabla: la flecha solo en la columna que manda. En
   la otra aparece al pasar por encima, para que se sepa que también ordena. */
.cu-table thead th:not(.is-sorted) .th-sort svg { opacity: 0; transition: opacity var(--t-fast) var(--ease); }
.cu-table thead th:not(.is-sorted) .th-sort:hover svg,
.cu-table thead th:not(.is-sorted) .th-sort:focus-visible svg { opacity: .5; }

/* ---- Las dos fechas del periodo personalizado ----
   Mismo envoltorio que los desplegables para que la barra no se descuadre al
   aparecer: la única diferencia es que el calendario lo abre el navegador y
   no hay galón propio que pintar. */
.fsel-date { min-width: 154px; }
.fsel-date input[type="date"] {
  width: 100%; height: 22px; padding: 0 0 0 3px;
  background: none; border: 0; outline: none; cursor: pointer;
  font-family: inherit; font-size: var(--fs-md); font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* El indicador nativo —y su parche de `invert(1)` para el tema oscuro— se
   fueron con el calendario del sistema: ahora el campo entero abre el
   calendario de la casa y el icono lo pinta components.css con los mismos
   tonos del galón de los selects. */
.fsel-date input[type="date"] {
  padding-right: 22px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%239aa1b1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='4' width='18' height='17' rx='2'/><path d='M16 2v4M8 2v4M3 10h18'/></svg>");
  background-repeat: no-repeat; background-position: right 2px center;
}
[data-theme="dark"] .fsel-date input[type="date"] {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236e7480' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='4' width='18' height='17' rx='2'/><path d='M16 2v4M8 2v4M3 10h18'/></svg>");
}
/* Variante compacta: la que va dentro del encabezado de una tarjeta */
.fsel-sm { min-width: 136px; height: 36px; padding: 0 var(--s3); justify-content: center; }
.fsel-sm select { height: auto; font-size: var(--fs-sm); }
.fsel-sm > svg { bottom: 50%; transform: translateY(50%); }

/* ---- Rejilla de las tarjetas grandes ---- */
.sales-split { display: grid; gap: var(--s5); grid-template-columns: minmax(0, 1.68fr) minmax(0, 1fr); }
.sales-split > .card { min-width: 0; display: flex; flex-direction: column; }
.sales-split > .card > .table-wrap { flex: 1 1 auto; }

/* ---- Reparto por plataforma ---- */
.plat-body { display: flex; align-items: center; gap: var(--s5); flex-wrap: wrap; }
.plat-legend { flex: 1 1 190px; min-width: 0; display: flex; flex-direction: column; gap: var(--s3); }
.plat-row { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.plat-total {
  display: flex; align-items: center; gap: var(--s2);
  padding-top: var(--s3); border-top: 1px solid var(--border-soft);
}

/* ---- Productos ---- */
.prod-ico {
  display: grid; place-items: center; flex: none;
  width: 35px; height: 35px; border-radius: var(--r-xs);
  font-size: var(--fs-sm); font-weight: 700; font-family: var(--font-display);
  overflow: hidden;
}
/* Con portada, el hueco es el mismo y la imagen lo cubre entera. Así el
   catálogo no baila según cuántos productos lleven imagen ya. */
.prod-ico.has-img { background: var(--surface-3); border: 1px solid var(--border); }
.prod-ico.has-img img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---- Portada en el formulario de producto ---- */
.pimg-field { display: flex; gap: var(--s4); align-items: flex-start; }
.pimg-prev {
  flex: none; display: grid; place-items: center; overflow: hidden;
  width: 96px; height: 96px; border-radius: var(--r-md);
  background: var(--surface-3); border: 1px solid var(--border);
}
.pimg-prev img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pimg-ini {
  font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 700;
  color: var(--ink-4);
}
.pimg-side { min-width: 0; flex: 1 1 auto; }
.pimg-side .hint { font-size: var(--fs-xs); color: var(--ink-4); }
/* El `input[type=file]` va oculto dentro de una etiqueta con aspecto de botón:
   el control nativo no se puede estilar y desentona con el resto del modal. */
.pimg-side label.btn { cursor: pointer; }
/* Siete columnas en la mitad estrecha de la rejilla. El aire lateral se
   recorta aquí y no en `.table`, que lo necesita en pantallas con menos
   columnas, y el nombre del producto se corta con puntos suspensivos antes que
   empujar a las cifras fuera de la tarjeta. */
.prod-table thead th {
  text-transform: none; letter-spacing: 0; font-size: var(--fs-xs); font-weight: 600;
}
.prod-table td, .prod-table th { white-space: nowrap; padding-left: var(--s3); padding-right: var(--s3); }
.prod-table td:first-child, .prod-table th:first-child { padding-left: var(--s4); }
.prod-table td:last-child, .prod-table th:last-child { padding-right: var(--s4); }
.prod-table td:first-child { max-width: 200px; }
.prod-table .prod-spark { width: 74px; padding-right: 0; }
.prod-table .t-clip { min-width: 0; }
/* La miniatura es adorno; las cifras son el dato. Cuando no caben las siete
   columnas, la que se va es la miniatura —antes que empujar los números a un
   desplazamiento horizontal que nadie descubre. */
@media (max-width: 1560px) {
  .prod-table .prod-spark, .prod-table th.prod-spark-h { display: none; }
}

/* ---- Actividad reciente ---- */
.act-list { display: flex; flex-direction: column; gap: var(--s4); }
.act-item { display: flex; align-items: flex-start; gap: var(--s3); }
.act-ico {
  display: grid; place-items: center; flex: none;
  width: 30px; height: 30px; border-radius: var(--r-xs);
  background: var(--neutral-soft); color: var(--ink-3);
}
.act-ico[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.act-ico[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.act-ico[data-tone="warning"] { background: var(--warning-soft); color: var(--warning); }
.act-ico[data-tone="info"]    { background: var(--info-soft);    color: var(--info); }
.act-title {
  display: block; font-size: var(--fs-md); font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.act-note {
  display: block; margin-top: 1px; font-size: var(--fs-xs); color: var(--ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.act-time { flex: none; padding-top: 2px; font-size: var(--fs-2xs); color: var(--ink-4); white-space: nowrap; }

/* ---- Piezas que la vista usaba sin tener regla propia ----
   La insignia de estado tomaba su tono de un atributo que nadie estilaba y
   salía gris: el estado de una venta es justo lo que hay que leer de un
   vistazo. Igual el punto de plataforma, que sin tamaño no se veía. */
.sales-view .badge[data-tone="success"],
.overlay .badge[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.sales-view .badge[data-tone="danger"],
.overlay .badge[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.sales-view .badge[data-tone="amber"],
.overlay .badge[data-tone="amber"]   { background: var(--warning-soft); color: var(--warning); }
.sales-view .badge[data-tone="muted"],
.overlay .badge[data-tone="muted"]   { background: var(--neutral-soft); color: var(--ink-3); }
.sales-view .dot, .overlay .dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  flex: none; vertical-align: -.05em;
}

/* ============================================================ OPEN TEST = */
/* La línea de negocio completa: panel, catálogo, campañas, tablero y soporte.
   Comparte con Ventas la barra de filtros y las tarjetas de indicador; lo de
   aquí es lo que no existía. */

.ot-kpis {
  display: grid; gap: var(--s4);
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}

/* ---- Encabezado del panel ---- */
.ot-head h1 { line-height: 1.1; }
.ot-minis { display: flex; gap: var(--s3); flex-wrap: wrap; }
.ot-mini {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s4) var(--s2) var(--s2);
  background: var(--surface); border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
}
.ot-mini-ico {
  display: grid; place-items: center; flex: none;
  width: 30px; height: 30px; border-radius: var(--r-xs);
  background: var(--neutral-soft); color: var(--ink-3);
}
.ot-mini-ico[data-tone="purple"] { background: var(--accent-soft); color: var(--accent); }
.ot-mini-ico[data-tone="teal"]   { background: var(--success-soft); color: var(--success); }
.ot-mini-ico[data-tone="amber"]  { background: var(--warning-soft); color: var(--warning); }
.ot-mini-vl {
  font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 600;
  line-height: 1.1; letter-spacing: -.02em;
}
.ot-mini-lb { font-size: var(--fs-2xs); color: var(--ink-4); }
.ot-range {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); color: var(--ink-3);
}
.ot-range svg { color: var(--ink-4); }

/* ---- Fila superior: los dos KPIs + la meta del mes ---- */
.ot-top { display: grid; gap: var(--s4); grid-template-columns: 1fr 1fr 1.4fr; }
/* ---- Evolución de ventas + países ---- */
.ot-evo-row { display: grid; gap: var(--s4); grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); }
/* ---- Grilla de dos tarjetas ---- */
.ot-grid2 { display: grid; gap: var(--s4); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.skpi-wide { margin: var(--s2) calc(var(--s5) * -1) calc(var(--s3) * -1); }

/* Aquí vivió el CSS del embudo (`.fn-*`). Se fue con `funnelChart` el
   27-ago-2026; ver la nota en views/opentest.js. */

/* La cifra en dólares de la fila de país reserva su ancho: una columna que
   baila según el importe se lee peor que una alineada. */
.ot-geo-usd { min-width: 9ch; text-align: right; }

/* El chip del logo de pago: blanco SIEMPRE, en los dos temas — el azul de
   Visa sobre la superficie oscura desaparecería, y las marcas de pago se
   imprimen así en todas partes. El color suelto es para la tarjeta genérica
   del fallback, que es un trazo `currentColor` sobre el blanco del chip. */
.pay-logo {
  display: inline-flex; align-items: center; justify-content: center;
  width: 27px; height: 17px; flex: none;
  background: #fff; border: 1px solid var(--border); border-radius: 4px;
  color: #667085;
}
.pay-logo svg { display: block; }

/* ---- Página de nueva campaña ----
   El formulario dejó el modal (27-ago-2026): once campos y tres áreas de
   texto piden una hoja. Ancho de lectura, no de pantalla: un input de 1500px
   no se rellena mejor, se rellena peor. */
.ot-form-page { max-width: 880px; margin: 0 auto; }
.ot-form-page .card-foot { display: flex; justify-content: flex-end; gap: var(--s3); }

/* ---- Rejilla de tres tarjetas del panel ---- */
.ot-grid3 { display: grid; gap: var(--s5); grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.3fr) minmax(0, 0.8fr); }
.ot-grid3 > .card { min-width: 0; display: flex; flex-direction: column; }
.ot-grid3 > .card > .table-wrap { flex: 1 1 auto; }

/* ---- Meta del mes ----
   El porcentaje grande hereda su color del tono (verde / ámbar / rojo según
   el ritmo del calendario), y la marca vertical sobre la barra señala dónde
   «debería» ir el mes hoy — por eso la barra deja ver lo que sobresale.

   EL RELLENO ES UN DEGRADADO ANCLADO A LA PISTA, NO AL TROZO PINTADO (pedido
   de Juan, 26-ago: «empieza en rojo y va llenándose hasta llegar a verde en
   el 100 %»). El truco: el degradado se dibuja como si midiera la pista
   entera —`background-size: 100·100/w %`— y el span, que mide w %, solo deja
   ver su primer tramo. Al 20 % se ve rojo; a medio mes, rojo→ámbar; el verde
   completo aparece exactamente al llegar a la meta. Pintar el degradado
   sobre el span a secas mostraría SIEMPRE el verde en la punta, que es
   justo lo que esta barra no debe decir. `--w` lo pone la vista (mínimo 1
   para no dividir entre cero). */
/* Cinco paradas, no tres (Juan, 26-ago): rojo → naranja → amarillo → verde
   claro → verde de la casa. Los extremos son tokens y siguen al tema; los
   tres intermedios no existen en la paleta —son puente perceptual, no
   estados— y van en hex a propósito. */
.ot-goal-bar > span {
  background: linear-gradient(90deg,
    var(--danger) 0%, #f97316 28%, #eab308 52%, #4ade80 78%, var(--success) 100%);
  background-size: calc(100% * 100 / var(--w, 100)) 100%;
  background-repeat: no-repeat;
}
.ot-goal-pct { font-size: var(--fs-xl); font-weight: 800; font-variant-numeric: tabular-nums; align-self: center; }
.ot-goal-vals { display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap; margin-bottom: var(--s3); }
.ot-goal-now { font-size: var(--fs-2xl); font-weight: 800; letter-spacing: -.015em; font-variant-numeric: tabular-nums; }
.ot-goal-of { color: var(--ink-3); font-size: var(--fs-sm); }
/* Un 25 % más gruesa que `.progress-lg` (10 px), pedido de Juan. Solo esta:
   engordar `.progress-lg` cambiaría las barras del resto de la plataforma.

   LA USAN DOS PANTALLAS, no solo Open Test (Juan, 15-sep: «la barra de Open
   Test me gusta, que la de renovaciones sea igual en grosor y color»): el
   «Meta del periodo» de Renovaciones lleva las mismas clases. El prefijo `ot-`
   se queda —igual que en `.ot-goal-pct`, que Renovaciones ya compartía— porque
   renombrarlo tocaría las dos vistas para no cambiar nada de lo que se ve.

   `overflow: visible` existe por la marca de ritmo, que solo pone Open Test.
   En Renovaciones no sobresale nada: el relleno nunca pasa del 100 %. */
.ot-goal-bar { overflow: visible; height: 12.5px; }
.ot-goal-mark {
  position: absolute; top: -4px; bottom: -4px; width: 2px;
  background: var(--ink-4); border-radius: 1px;
}

/* Una serie que todavía no existe se nombra en la leyenda, atenuada: así se ve
   que el gráfico está incompleto y no que solo había una línea que dibujar. */
.legend-item.is-off { color: var(--ink-4); }
.legend-item.is-off .legend-swatch { background: var(--border-strong); }

/* ---- Soporte y satisfacción ---- */
.ot-tri { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); }
.ot-tri-lb { display: block; font-size: var(--fs-2xs); color: var(--ink-4); line-height: 1.3; }
.ot-tri-vl {
  display: block; margin-top: 2px;
  font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 600;
  letter-spacing: -.02em; line-height: 1.1;
}
.ot-sat {
  margin-top: var(--s5); padding-top: var(--s4);
  border-top: 1px solid var(--border-soft);
}
.ot-sat-vl {
  display: block; margin: 2px 0;
  font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 600;
  color: var(--ink-4); letter-spacing: -.02em; line-height: 1.1;
}

/* ---- Catálogo en tarjetas ---- */
.ot-pgrid {
  display: grid; gap: var(--s4);
  grid-template-columns: repeat(auto-fill, minmax(276px, 1fr));
}
.ot-pcard {
  display: flex; flex-direction: column; gap: var(--s3);
  padding: var(--s5); color: inherit;
}
.ot-pcard:hover { text-decoration: none; }
.ot-pcard-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s3); }
/* Tres tamaños, uno por sitio, porque la portada no cumple la misma función en
   cada uno: en una fila de tabla acompaña al nombre, en el catálogo ES lo que
   se reconoce de un vistazo, y en la ficha del producto es el producto.
   Antes la ficha y las tarjetas compartían los 40 px de `is-lg` y en ninguno de
   los dos se veía la imagen. */
.prod-ico.is-lg { width: 125px; height: 125px; font-size: var(--fs-3xl); border-radius: var(--r-md); }

/* La ficha del producto enseña la portada casi a tamaño real. No lleva medida
   fija sino `min(500px, 100%)` con proporción cuadrada: a 500 px de ancho fijo,
   en un móvil se saldría de la pantalla, y con `max-width` a secas la caja se
   deformaría porque el alto seguiría siendo 500. */
.prod-ico.is-xl {
  width: min(500px, 100%); height: auto; aspect-ratio: 1;
  border-radius: var(--r-xl);
}
/* La inicial NO se estira con el hueco: sigue siendo un marcador de posición y
   una letra suelta de 500 px grita mucho más que la portada que sustituye. */
.prod-ico.is-xl:not(.has-img) { font-size: var(--fs-hero); }
.ot-pcard-name {
  font-size: var(--fs-base); font-weight: 600; color: var(--ink); line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden; min-height: 2.6em;
}
.ot-pcard-fam { display: flex; gap: var(--s2); flex-wrap: wrap; }
.ot-pcard-kpis {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s2);
  padding-top: var(--s3); border-top: 1px solid var(--border-soft);
}
.ot-pcard-kpis .lb { display: block; font-size: var(--fs-3xs); color: var(--ink-4); line-height: 1.3; }
.ot-pcard-kpis .vl {
  display: block; font-family: var(--font-display); font-size: var(--fs-md);
  font-weight: 600; letter-spacing: -.02em; white-space: nowrap;
}
.ot-pcard-spark { margin: 0 calc(var(--s5) * -1); }
.ot-pcard-foot { display: flex; align-items: center; gap: var(--s3); }
.ot-pcard-foot .progress { flex: 1 1 auto; }

/* ---- Ficha de producto ---- */
.crumb-back {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink-3);
}
.crumb-back:hover { color: var(--primary); text-decoration: none; }
.ot-phead h1 { font-size: var(--fs-2xl); }
.ot-phead .actions { align-items: flex-start; }

/* Encabezado de sección dentro de una pantalla. Separa «lo que sí se sabe» de
   «lo que no» sin abrir dos pantallas para decirlo. */
.ot-sec {
  display: flex; align-items: center; gap: var(--s3);
  margin: var(--s7) 0 var(--s4);
}
.ot-sec:first-of-type { margin-top: var(--s5); }
.ot-sec h2 { font-size: var(--fs-lg); }
.ot-sec .sub { font-size: var(--fs-xs); color: var(--ink-3); margin-top: 2px; }
.ot-sec-ico {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: var(--r-sm);
  background: var(--surface-3); color: var(--ink-3);
}

/* Las tarjetas .ot-na (dato sin fuente) se retiraron el 21-sep-2026. */

/* ---- Fila que lleva a otra pantalla ---- */
.ot-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); margin: 0 calc(var(--s3) * -1);
  border-radius: var(--r-md); color: inherit;
  transition: background var(--t-fast) var(--ease);
}
.ot-row:hover { background: var(--surface-2); text-decoration: none; }
.ot-row-ico {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: var(--r-sm);
  background: var(--primary-soft); color: var(--primary);
}
.ot-row-t { display: block; font-size: var(--fs-md); font-weight: 600; }
.ot-row-s { display: block; font-size: var(--fs-xs); color: var(--ink-3); }
.ot-row > svg { color: var(--ink-4); flex: none; }

/* ---- Campañas ---- */
.ot-cards {
  display: grid; gap: var(--s4);
  grid-template-columns: repeat(auto-fill, minmax(288px, 1fr));
}
.ot-card { padding: var(--s4) var(--s5); text-align: left; cursor: pointer; }
.ot-card-t { font-size: var(--fs-md); font-weight: 600; color: var(--ink); line-height: 1.35; }
.ot-card-meta {
  display: flex; flex-wrap: wrap; gap: var(--s1) var(--s4);
  margin-top: var(--s3); padding-top: var(--s3);
  border-top: 1px solid var(--border-soft);
}
.ot-card-meta > span {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-2xs); color: var(--ink-3); min-width: 0;
}
.ot-card-meta svg { color: var(--ink-4); }

/* ---- Conversación de un ticket ---- */
.ot-notes { display: flex; flex-direction: column; gap: var(--s3); max-height: 320px; overflow-y: auto; }
.ot-note {
  padding: var(--s3) var(--s4);
  background: var(--surface-2); border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
}
/* La nota interna se distingue de un vistazo: confundir una nota con una
   respuesta enviada es mandarle a alguien de fuera lo que no debía leer. */
.ot-note.is-internal { background: var(--warning-soft); border-color: transparent; }

@media (max-width: 1280px) {
  .ot-top { grid-template-columns: 1fr 1fr; }
  .ot-top > .card:last-child { grid-column: 1 / -1; }
  .ot-evo-row { grid-template-columns: minmax(0, 1fr); }
  .ot-grid3 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .ot-grid3 > .card:first-child { grid-column: 1 / -1; }
}
@media (max-width: 860px) {
  .ot-top { grid-template-columns: minmax(0, 1fr); }
  .ot-top > .card:last-child { grid-column: auto; }
  .ot-evo-row { grid-template-columns: minmax(0, 1fr); }
  .ot-grid2 { grid-template-columns: minmax(0, 1fr); }
  .ot-grid3 { grid-template-columns: minmax(0, 1fr); }
  .ot-grid3 > .card:first-child { grid-column: auto; }
  .ot-minis { width: 100%; }
}
@media (max-width: 720px) {
  .ot-sec { margin-top: var(--s6); }
}

/* ---- Pantallas estrechas ---- */
@media (max-width: 1400px) {
  .skpi-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 1180px) {
  .sales-top, .sales-split { grid-template-columns: minmax(0, 1fr); }
  .ai-list { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 860px) {
  .skpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fsel { min-width: 132px; flex: 1 1 132px; }
}
@media (max-width: 560px) {
  .skpi-row { grid-template-columns: minmax(0, 1fr); }
  .skpi-trend { display: none; }
  .hs-body { flex-direction: column; align-items: flex-start; }
}

/* ==========================================================================
   MESA DE AYUDA · historial de un ticket

   La conversación reutiliza las clases del service desk (.sd-thread, .sd-msg,
   .sd-props): es el mismo objeto visto por otra puerta, y darle un aspecto
   propio solo conseguiría que dos pantallas de la misma plataforma no se
   parezcan. Lo único nuevo aquí es la línea de tiempo, que allá no existe.
   ========================================================================== */
.tl { display: flex; flex-direction: column; gap: var(--s4); }
.tl-item { display: flex; gap: var(--s3); align-items: flex-start; min-width: 0; }
.tl-ico {
  flex: none; width: 26px; height: 26px; border-radius: var(--r-full);
  display: grid; place-items: center;
  background: var(--surface-3); color: var(--ink-3);
}
.tl-item[data-tone="primary"] .tl-ico { background: var(--primary-soft); color: var(--primary); }
.tl-item[data-tone="amber"]   .tl-ico { background: var(--warning-soft); color: var(--warning); }
.tl-item[data-tone="danger"]  .tl-ico { background: var(--danger-soft);  color: var(--danger); }
.tl-item[data-tone="success"] .tl-ico { background: var(--success-soft); color: var(--success); }
.tl-body { flex: 1 1 auto; min-width: 0; }
.tl-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.tl-who { font-size: var(--fs-sm); font-weight: 600; color: var(--ink); }
.tl-when { font-size: var(--fs-2xs); color: var(--ink-4); margin-left: auto; white-space: nowrap; }
.tl-tx {
  font-size: var(--fs-md); color: var(--ink-2); white-space: pre-wrap;
  margin-top: 4px; overflow-wrap: anywhere;
}

/* La novedad sin leer. Un punto y un filo de 3 px: es la misma marca que lleva
   un ticket vencido en la cola externa (.sd-row.is-late), así que quien ya usa
   una pantalla reconoce la otra sin aprender nada nuevo. */
.dot-new { flex: none; width: 7px; height: 7px; border-radius: var(--r-full); background: var(--primary); }
.ticket-row.is-unread { box-shadow: inset 3px 0 0 var(--primary); }

@media (max-width: 860px) {
  .tl-when { margin-left: 0; }
}

/* ========================================================== RENOVACIONES = */
/* La sección reutiliza las piezas de Ventas —.sales-split, .plat-body,
   .kpi-mini— porque enseña lo mismo con otro alcance. Lo único suyo es la
   tarjeta que declara la frontera de las cifras, y es plegable a propósito:
   tiene que estar SIEMPRE a la vista de quien lee el total, y no ocupar media
   pantalla de quien ya sabe qué está mirando. */
.ren-scope { padding: 0; }
.ren-scope > summary {
  cursor: pointer; list-style: none; user-select: none;
  border-bottom: 0; transition: background var(--t-fast);
}
.ren-scope > summary::-webkit-details-marker { display: none }
.ren-scope > summary:hover { background: var(--surface-2); }
.ren-scope > summary:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.ren-scope > summary h3 { display: flex; align-items: center; gap: var(--s2); }
/* Al abrirse aparece el contenido y la cabecera necesita su línea: cerrada no,
   porque una tarjeta de una sola fila con una raya debajo se ve partida. */
.ren-scope[open] > summary { border-bottom: 1px solid var(--border); }

/* Ventas email (0133). Una barra por correo, de la misma familia que las de
   Plataformas: rótulo, barra, ventas e ingreso, alineados en columnas. */
.vem-mails { display: grid; gap: var(--s2); }
.vem-mail-row {
  display: grid; align-items: center; gap: var(--s3);
  grid-template-columns: 74px minmax(0, 1fr) 48px 96px;
}
.vem-mail-row > :nth-child(3), .vem-mail-row > :nth-child(4) { text-align: right; }
.vem-bar { display: block; height: 8px; border-radius: 4px; background: var(--surface-3); overflow: hidden; }
.vem-bar > i { display: block; height: 100%; border-radius: 4px; background: var(--c1); min-width: 2px; }

/* ======================================================= KNOWLEDGE BASE = */
/* La forma es la de Slite: un árbol fijo a la izquierda, el documento en el
   centro y la ficha a la derecha. Lo importante de esa forma no es el reparto
   de columnas — es que EL ÁRBOL NO SE VA al entrar a leer. Ahí está la
   diferencia entre navegar la documentación y buscarla a ciegas: quien llega
   por un enlace ve dónde ha caído y qué hay al lado. */

.kb-view {
  display: grid;
  grid-template-columns: 268px minmax(0, 1fr);
  gap: var(--s6);
  align-items: start;
}
@media (max-width: 1100px) {
  .kb-view { grid-template-columns: minmax(0, 1fr); }
  .kb-side { display: none; }
}

/* ---- Barra del árbol ---- */
.kb-side {
  position: sticky; top: var(--s5);
  max-height: calc(100vh - var(--s8));
  overflow-y: auto; overscroll-behavior: contain;
  padding-right: var(--s2);
  border-right: 1px solid var(--border);
}
.kb-side::-webkit-scrollbar { width: 6px; }
.kb-side::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--r-full); }

.kb-side-top { display: flex; flex-direction: column; gap: 3px; margin-bottom: var(--s5); }
.kb-side-h {
  padding: 0 var(--s2) var(--s2);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-4);
}

/* El botón de Ask va ARRIBA DEL TODO y es el único elemento con relleno de
   marca de toda la barra. En Slite preguntar es la acción principal, no una
   más: quien no sabe dónde está algo pregunta antes que navegar. */
.kb-ask-btn {
  display: flex; align-items: center; gap: var(--s2);
  width: 100%; padding: 9px var(--s3); margin-bottom: var(--s2);
  background: var(--primary-soft); color: var(--primary);
  border: 1px solid transparent; border-radius: var(--r-sm);
  font-size: var(--fs-sm); font-weight: 600; text-align: left;
  transition: background var(--t-fast) var(--ease);
}
.kb-ask-btn:hover { background: var(--primary-soft-2); }
.kb-ask-btn svg { width: 15px; height: 15px; flex: none; }
.kb-ask-btn kbd {
  padding: 1px 5px; font-size: 10px; font-family: var(--font-mono);
  background: var(--surface); color: var(--ink-4);
  border: 1px solid var(--border); border-radius: 4px;
}

.kb-side-link {
  display: flex; align-items: center; gap: var(--s2);
  padding: 7px var(--s3); border-radius: var(--r-sm);
  font-size: var(--fs-sm); color: var(--ink-2);
}
.kb-side-link:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
.kb-side-link.is-active { background: var(--surface-3); color: var(--ink); font-weight: 600; }
.kb-side-link svg { width: 15px; height: 15px; flex: none; }

.kb-canal { margin-bottom: 2px; }
.kb-canal-h, .kb-leaf {
  display: flex; align-items: center; gap: 6px;
  padding: 6px var(--s2); border-radius: var(--r-sm);
  font-size: var(--fs-sm); color: var(--ink-2);
  min-width: 0;
}
.kb-canal-h { font-weight: 600; color: var(--ink); }
.kb-canal-h:hover, .kb-leaf:hover { background: var(--surface-2); text-decoration: none; }
.kb-canal-h.is-active { color: var(--primary); }
.kb-leaf.is-active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }

/* El chevron ocupa su hueco aunque no haya hijos. Sin el hueco, los títulos de
   los documentos con hijos y sin hijos arrancan en columnas distintas y el
   árbol deja de leerse como un árbol. */
.kb-caret {
  display: grid; place-items: center; width: 14px; height: 14px; flex: none;
  color: var(--ink-4);
  transition: transform var(--t-fast) var(--ease);
}
.kb-caret svg { width: 12px; height: 12px; }
.kb-caret.is-open { transform: rotate(90deg); }
.kb-caret.is-empty { visibility: hidden; }

.kb-canal-ico, .kb-leaf-ico { display: grid; place-items: center; flex: none; }
.kb-canal-ico svg, .kb-leaf-ico svg { width: 14px; height: 14px; }
.kb-leaf-ico { color: var(--ink-4); }
.kb-leaf.is-active .kb-leaf-ico { color: var(--primary); }
.kb-mio { display: grid; place-items: center; color: var(--ink-4); }
.kb-mio svg { width: 12px; height: 12px; }

/* La línea vertical de la rama: es lo que hace visible la profundidad sin
   contar sangrías. */
.kb-branch { margin-left: 13px; border-left: 1px solid var(--border); }
.kb-vacio { padding: 6px var(--s3); font-size: var(--fs-2xs); color: var(--ink-4); }

/* Un punto, no una insignia: en el árbol hay treinta filas y treinta insignias
   son treinta cosas gritando. El punto dice «mira esto» y el título sigue
   siendo lo que se lee. */
.kb-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.kb-dot[data-tone="stale"] { background: var(--warning); }
.kb-dot[data-tone="draft"] { background: var(--ink-4); }

/* ---- Zona central ---- */
.kb-main { min-width: 0; }
.kb-main-doc {
  display: grid; grid-template-columns: minmax(0, 1fr) 244px; gap: var(--s6);
  align-items: start;
}
@media (max-width: 1400px) {
  .kb-main-doc { grid-template-columns: minmax(0, 1fr); }
  .kb-aside { display: none; }
}

.kb-ask-hero {
  display: flex; align-items: center; gap: var(--s3);
  width: 100%; padding: var(--s4) var(--s5); margin-bottom: var(--s6);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-xs);
  font-size: var(--fs-base); color: var(--ink-3); text-align: left;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.kb-ask-hero:hover { border-color: var(--primary); box-shadow: var(--shadow-sm); }
.kb-ask-hero svg { width: 19px; height: 19px; flex: none; color: var(--primary); }
.kb-ask-hero kbd {
  padding: 2px 7px; font-size: 11px; font-family: var(--font-mono);
  background: var(--surface-2); color: var(--ink-4);
  border: 1px solid var(--border); border-radius: 5px;
}

/* ---- Tarjetas de canal ---- */
.kb-cards { display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
.kb-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: var(--s4);
  display: flex; flex-direction: column; gap: var(--s3);
}
.kb-card-h { display: flex; gap: var(--s3); align-items: flex-start; color: inherit; }
.kb-card-h:hover { text-decoration: none; }
.kb-card-h:hover .t-semi { color: var(--primary); }
.kb-card-ico {
  display: grid; place-items: center; width: 34px; height: 34px; flex: none;
  background: var(--primary-soft); color: var(--primary); border-radius: var(--r-sm);
}
.kb-card-ico svg { width: 17px; height: 17px; }
.kb-card-meta { display: flex; gap: var(--s2); flex-wrap: wrap; }
.kb-card-meta:empty { display: none; }
.kb-card-kids { display: flex; flex-direction: column; gap: 2px; border-top: 1px solid var(--border); padding-top: var(--s3); }
.kb-card-kids a {
  display: flex; align-items: center; gap: 6px; min-width: 0;
  padding: 3px 0; font-size: var(--fs-sm); color: var(--ink-3);
}
.kb-card-kids a:hover { color: var(--primary); text-decoration: none; }
.kb-card-kids svg { width: 13px; height: 13px; flex: none; }

/* ---- Choque de nombres con el tablero ----
   `.kb-cards` y `.kb-card` son a la vez la columna del tablero (sección KANBAN,
   arriba) y las tarjetas de canal de esta Knowledge Base. Estas reglas cargan
   después y convertían cada columna de Mi tablero y de JIRA en una rejilla de
   300 px de mínimo: de ahí la barra de desplazamiento horizontal bajo cada
   columna. El tablero recupera lo suyo por ancestro. */
.kanban .kb-cards {
  display: flex; flex-direction: column; gap: var(--s2);
  grid-template-columns: none; overflow-x: hidden;
}
.kanban .kb-card { display: block; gap: 0; padding: var(--s3); border-radius: var(--r-md); }

/* ---- Resultado / fila de documento ---- */
.kb-hit {
  display: flex; gap: var(--s3); align-items: flex-start;
  padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border);
  color: inherit;
}
.kb-hit:last-child { border-bottom: 0; }
.kb-hit:hover { background: var(--surface-2); text-decoration: none; }
.kb-hit-ico {
  display: grid; place-items: center; width: 30px; height: 30px; flex: none;
  background: var(--surface-3); color: var(--ink-3); border-radius: var(--r-sm);
}
.kb-hit-ico svg { width: 15px; height: 15px; }
.kb-passage {
  display: block; margin-top: 3px;
  font-size: var(--fs-sm); color: var(--ink-2); line-height: 1.5;
  border-left: 2px solid var(--border-strong); padding-left: var(--s3);
}
.kb-crumb-mini {
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin-top: 5px;
  font-size: var(--fs-2xs); color: var(--ink-4);
}
.kb-crumb-mini svg { width: 11px; height: 11px; }

/* ---- Ask ---- */
.kb-ask { margin: calc(var(--s5) * -1); }
.kb-ask-in {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4) var(--s5); border-bottom: 1px solid var(--border);
}
.kb-ask-in > svg { width: 20px; height: 20px; flex: none; color: var(--primary); }
.kb-ask-input {
  flex: 1; min-width: 0; border: 0; background: transparent;
  font-family: inherit; font-size: var(--fs-lg); color: var(--ink);
}
.kb-ask-input:focus { outline: none; }
.kb-ask-input::placeholder { color: var(--ink-4); }

/* La aclaración va DENTRO del buscador y no en un pie: es donde se lee antes de
   escribir, que es cuando todavía sirve para no esperar lo que no va a llegar. */
.kb-ask-note {
  display: flex; gap: var(--s2); align-items: flex-start;
  padding: var(--s3) var(--s5);
  background: var(--info-soft); color: var(--ink-2);
  font-size: var(--fs-2xs); line-height: 1.5;
}
.kb-ask-note svg { width: 13px; height: 13px; flex: none; margin-top: 1px; color: var(--info); }

.kb-ask-out { max-height: 54vh; overflow-y: auto; }
.kb-ask-count {
  padding: var(--s3) var(--s5) var(--s2);
  font-size: var(--fs-2xs); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-4);
}
.kb-ask-empty { padding: var(--s7) var(--s5); text-align: center; font-size: var(--fs-sm); color: var(--ink-4); }

/* ---- El documento ---- */
.kb-doc { min-width: 0; }
.kb-trust {
  display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
  padding-bottom: var(--s3); margin-bottom: var(--s3);
  border-bottom: 1px solid var(--border);
}
.kb-owner { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-2xs); color: var(--ink-3); }

.kb-title {
  display: flex; align-items: center; gap: var(--s3);
  font-family: var(--font-display); font-size: var(--fs-3xl); line-height: 1.15;
  color: var(--ink); margin-bottom: var(--s2);
}
.kb-title-ico {
  display: grid; place-items: center; width: 38px; height: 38px; flex: none;
  background: var(--primary-soft); color: var(--primary); border-radius: var(--r-md);
}
.kb-title-ico svg { width: 20px; height: 20px; }
.kb-lead { font-size: var(--fs-base); color: var(--ink-3); line-height: 1.6; max-width: 72ch; }
.kb-actions { display: flex; gap: var(--s2); flex-wrap: wrap; margin-top: var(--s4); }

/* El cuerpo se estrecha a 76 caracteres. No es estética: por encima de ~90 el
   ojo pierde el renglón al volver, y un procedimiento se lee entero. */
.kb-body { max-width: 76ch; margin-top: var(--s6); }
.kb-body h3 {
  margin: var(--s6) 0 var(--s3); font-size: var(--fs-lg);
  font-family: var(--font-display); color: var(--ink);
  scroll-margin-top: var(--s6);
}
.kb-body h3:first-child { margin-top: 0; }
.kb-body > *:last-child { margin-bottom: 0; }

.kb-note {
  display: flex; gap: var(--s3); align-items: flex-start;
  margin: var(--s4) 0; padding: var(--s3) var(--s4);
  border: 1px solid var(--info);
  background: var(--info-soft); border-radius: var(--r-sm);
  font-size: var(--fs-sm); color: var(--ink-2);
}
.kb-note svg { width: 16px; height: 16px; flex: none; margin-top: 2px; color: var(--info); }
.kb-note[data-tone="warning"] { border-left-color: var(--warning); background: var(--warning-soft); }
.kb-note[data-tone="warning"] svg { color: var(--warning); }
.kb-note[data-tone="danger"]  { border-left-color: var(--danger);  background: var(--danger-soft); }
.kb-note[data-tone="danger"] svg { color: var(--danger); }
.kb-note[data-tone="success"] { border-left-color: var(--success); background: var(--success-soft); }
.kb-note[data-tone="success"] svg { color: var(--success); }

/* `pre-wrap` no es un detalle de estilo: los saltos de línea SON el formato de
   un correo o una firma, y convertirlos en párrafos los reescribiría. */
.kb-quote, .kb-code {
  position: relative;
  margin: var(--s4) 0; padding: var(--s4) var(--s5); padding-right: 92px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-sm);
  white-space: pre-wrap; word-break: break-word;
}
.kb-quote { font-size: var(--fs-sm); color: var(--ink-2); line-height: 1.65; }
.kb-code { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink); overflow-x: auto; }
.kb-copy {
  position: absolute; top: var(--s3); right: var(--s3);
  opacity: 0; transition: opacity var(--t-fast) var(--ease);
}
.kb-quote:hover .kb-copy, .kb-code:hover .kb-copy, .kb-copy:focus-visible { opacity: 1; }
@media (hover: none) { .kb-copy { opacity: 1; } }

.kb-table thead th, .kb-table tbody td { padding: var(--s2) var(--s3); font-size: var(--fs-sm); }
.kb-body .table-wrap { margin: var(--s4) 0; }

/* ---- Lo que cuelga del documento ---- */
.kb-subdocs {
  margin-top: var(--s7); padding-top: var(--s5);
  border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 2px;
}
.kb-subdocs-h {
  display: flex; align-items: center; gap: 6px; margin-bottom: var(--s2);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-4);
}
.kb-subdocs-h svg { width: 13px; height: 13px; }
.kb-subdocs > a {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); border-radius: var(--r-sm); color: inherit;
}
.kb-subdocs > a:hover { background: var(--surface-2); text-decoration: none; }
.kb-subdocs > a > svg:first-child { width: 16px; height: 16px; flex: none; color: var(--ink-4); }
.kb-subdocs b { display: block; font-size: var(--fs-md); }
.kb-subdocs span > span { display: block; font-size: var(--fs-xs); color: var(--ink-4); margin-top: 1px; }

.kb-foot {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  margin-top: var(--s6); padding: var(--s4);
  background: var(--surface-2); border-radius: var(--r-md);
}

/* ---- Columna derecha ---- */
.kb-aside { position: sticky; top: var(--s5); display: flex; flex-direction: column; gap: var(--s5); }
.kb-outline { display: flex; flex-direction: column; gap: 1px; }
.kb-outline-h {
  margin-bottom: var(--s2);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-4);
}
.kb-outline a {
  padding: 5px var(--s3); border-left: 2px solid var(--border);
  font-size: var(--fs-sm); color: var(--ink-3);
}
.kb-outline a:hover { border-left-color: var(--primary); color: var(--primary); text-decoration: none; }
.kb-aside-card {
  padding: var(--s4); background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--r-md);
}
.kb-aside-card .dl { font-size: var(--fs-xs); }

/* ---- Plantillas ---- */
.kb-tpl { display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
.kb-tpl-card {
  display: flex; flex-direction: column; gap: 6px; align-items: flex-start;
  padding: var(--s4); text-align: left;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.kb-tpl-card:hover { border-color: var(--primary); background: var(--primary-soft); }
.kb-tpl-card b { font-size: var(--fs-md); color: var(--ink); }
.kb-tpl-card span:last-child { font-size: var(--fs-xs); color: var(--ink-3); line-height: 1.5; }
.kb-tpl-ico {
  display: grid; place-items: center; width: 30px; height: 30px;
  background: var(--surface-3); color: var(--ink-2); border-radius: var(--r-sm);
}
.kb-tpl-card:hover .kb-tpl-ico { background: var(--primary); color: #fff; }
.kb-tpl-ico svg { width: 15px; height: 15px; }

/* ---- Piezas compartidas ---- */
/* Los tonos de insignia estaban resueltos solo dentro de .sales-view y de los
   modales. La Knowledge Base rotula ocho tipos de documento con esos mismos
   tonos y vive fuera de ambos, así que se declaran para su propia clase en vez
   de ensanchar un selector ajeno. */
.badge.kb-tone[data-tone="primary"] { background: var(--primary-soft); color: var(--primary); }
.badge.kb-tone[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.badge.kb-tone[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.badge.kb-tone[data-tone="amber"]   { background: var(--warning-soft); color: var(--warning); }
.badge.kb-tone[data-tone="teal"]    { background: var(--info-soft);    color: var(--info); }
.badge.kb-tone[data-tone="purple"]  { background: var(--accent-soft);  color: var(--accent); }
.badge.kb-tone[data-tone="muted"]   { background: var(--neutral-soft); color: var(--ink-3); }

.chip-sm { height: 24px; padding: 0 var(--s2); font-size: var(--fs-2xs); }
.chip-sm svg { width: 12px; height: 12px; }
.kb-chips { display: flex; gap: var(--s2); flex-wrap: wrap; }

.btn-xs {
  height: 26px; padding: 0 var(--s2); font-size: var(--fs-2xs);
  border-radius: var(--r-xs); gap: 5px;
}
.btn-xs svg { width: 13px; height: 13px; }

/* ===================================================== PRESENCIA ======= */
/* La tarjeta de «quién está trabajando». Se incrusta en el panel de Gerencia
   y en Asistencia, así que todo va bajo `.pres-card` y no toca nada de fuera. */

.pres-counts {
  display: grid; gap: var(--s2);
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
}

/* Cada contador es un botón que filtra. El punto de color lo lleva el propio
   botón vía `--d`, que es lo que manda la taxonomía de estados en JS: así el
   color del estado se declara UNA vez y no dos veces, aquí y allá. */
.pres-count {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: var(--s2) var(--s3);
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-2); cursor: pointer; text-align: left;
  /* NO se transiciona `background`, y no es estética.
   *
   * Al transicionar una propiedad cuyo valor sale de un token, el navegador
   * congela el color resuelto la primera vez y deja de seguir el token: el
   * botón se quedaba con el fondo del tema en el que se pintó y no cambiaba al
   * conmutar a oscuro, mientras la tarjeta de al lado sí. Se ve solo mirando
   * el OTRO tema, que es por lo que hay que mirarlo siempre.
   *
   * Es el mismo fallo que apareció en las barras horizontales de `charts.js`. */
  transition: border-color .14s ease;
}
.pres-count:hover { border-color: var(--ink-4); }
.pres-count.is-on { border-color: var(--d); background: color-mix(in srgb, var(--d) 8%, var(--surface-2)); }
.pres-count .vl {
  font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 600;
  line-height: 1.1; letter-spacing: -.02em;
}
.pres-count .lb {
  font-size: var(--fs-2xs); color: var(--ink-3); font-weight: 600;
  display: flex; align-items: center; gap: 5px;
}
.pres-count .lb::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: var(--d); flex: none;
}

.pres-list { display: flex; flex-direction: column; }
.pres-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) 0; border-top: 1px solid var(--border);
}
.pres-row:first-child { border-top: 0; }

/* El punto de estado. Solo el de «trabajando» late: si latieran todos, el
   movimiento dejaría de significar nada. */
.pres-dot {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--d);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--d) 18%, transparent);
}
.pres-row:has(.badge-success) .pres-dot { animation: pres-latido 2.4s ease-in-out infinite; }

@keyframes pres-latido {
  0%, 100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--d) 18%, transparent); }
  50%      { box-shadow: 0 0 0 6px color-mix(in srgb, var(--d) 6%, transparent); }
}

/* Quien pidió menos movimiento no recibe un punto latiendo en la pantalla. */
@media (prefers-reduced-motion: reduce) {
  .pres-row:has(.badge-success) .pres-dot { animation: none; }
}

/* ======================================================== BANDERAS ===== */
/* Windows no trae ninguna fuente con banderas —Segoe UI Emoji las omite a
   proposito— asi que `🇨🇴` se dibuja como dos letras «CO» pequeñas. Poniendo
   `Noto Color Emoji` PRIMERO en la pila, el navegador saca de ahi el par de
   indicadores regionales y dibuja la bandera de verdad; todo lo demas sigue
   cayendo a la tipografia de siempre.

   La clase se aplica SOLO al hueco de la bandera. Ponerla en un contenedor
   arrastraria el texto de al lado a una fuente de emoji. */
.flag {
  font-family: 'Noto Color Emoji', 'Apple Color Emoji', 'Segoe UI Emoji', sans-serif;
  font-size: 1.05em; line-height: 1; flex: none;
  /* Sin esto, el glifo empuja la linea base de la fila hacia abajo. */
  vertical-align: -.08em;
}
.flag-lg { font-size: 1.6em; }

/* El hueco reservado es el mismo con bandera y sin ella, para que una columna
   de paises no baile segun cual tenga glifo disponible. */
.flag-slot { display: inline-flex; width: 1.35em; justify-content: center; }

/* ============================================ EXPLORADOR POR PAIS ====== */
/* Maestro-detalle: la lista de paises manda, el panel de la derecha obedece.
   En movil se apilan, con la lista arriba y limitada en alto para que el
   detalle no quede a tres pantallas de scroll. */

/* `align-items: stretch` --el valor por defecto, escrito a proposito-- para que
   la lista de paises llegue hasta abajo del panel de la derecha.
 *
   Antes era `start` con `max-height: 560px`: la lista terminaba a media altura
   y, como el borde divisorio va en ella, el resto de la columna quedaba en
   blanco y sin linea. Parecia que faltaba algo. */
.pd-split {
  display: grid; grid-template-columns: minmax(220px, 280px) minmax(0, 1fr);
  align-items: stretch;
}
.pd-list {
  display: flex; flex-direction: column;
  border-right: 1px solid var(--border);
  /* `min-height: 0` es lo que hace posible el scroll dentro de una rejilla: sin
     el, un elemento estirado se niega a encogerse por debajo de su contenido y
     `overflow` no llega a activarse nunca. */
  min-height: 0; overflow-y: auto;
}
.pd-detail { padding: var(--s4) var(--s5); min-width: 0; }

/* Cada pais es un boton con una barra de fondo que dice cuanto pesa sobre el
   primero. Asi la lista ES el grafico y no hace falta uno aparte. */
.pd-item {
  position: relative; display: block; width: 100%; text-align: left;
  padding: var(--s3) var(--s4); border: 0; background: none; cursor: pointer;
  border-bottom: 1px solid var(--border); overflow: hidden;
  /* `flex: none` NO es decorativo: sin él la lista aplasta las filas.
   *
   * `.pd-list` es flex en columna con `max-height`, y los hijos de un flex se
   * ENCOGEN por defecto para caber en el contenedor. Con veinte países, las
   * filas pasaban de sus 48 px naturales a 28 y el texto se montaba sobre la
   * barra de proporción. Medido antes y después: 28,06 px -> 48,25 px.
   *
   * Con esto la lista hace lo que debía desde el principio: mantener el alto de
   * cada fila y DESPLAZARSE cuando no caben. */
  flex: none;
}
.pd-item:last-child { border-bottom: 0; }
.pd-bar {
  position: absolute; inset: 0 auto 0 0; z-index: 0;
  background: var(--primary-soft);
  /* Sin `transition: width`. La barra nace ya con su ancho --la vista se
     repinta entera-- asi que la animacion no llegaba a verse nunca, y animar
     el ancho es trabajo de maquetacion en cada fotograma. */
}
.pd-item-in {
  position: relative; z-index: 1;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
}
.pd-item-v { font-size: var(--fs-2xs); font-weight: 600; color: var(--ink-3); flex: none; }
.pd-item:hover .pd-item-v { color: var(--ink-2); }
/* El elegido se marca con una barra lateral y peso, no solo con color de
   fondo: el fondo ya lo usa la barra de proporcion y competirian. */
.pd-item.is-on { background: var(--surface-2); box-shadow: inset 3px 0 0 var(--primary); }
.pd-item.is-on .pd-item-v { color: var(--primary); }

.pd-head {
  display: flex; flex-direction: column; gap: var(--s3);
  padding-bottom: var(--s4); margin-bottom: var(--s4);
  border-bottom: 1px solid var(--border);
}
.pd-title { font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 600; }
.pd-stats { display: grid; gap: var(--s2); grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }

@media (max-width: 900px) {
  .pd-split { grid-template-columns: minmax(0, 1fr); }
  .pd-list { border-right: 0; border-bottom: 1px solid var(--border); max-height: 260px; }
  .pd-detail { padding: var(--s4) var(--s4) var(--s5); }
}

/* ========================================== PANEL DE GERENCIA ========== */
/* La cabecera y las pestañas de área. Las comparten la Vista general y la
   pestaña de Ventas, para que saltar de una a otra se lea como cambiar de
   pestaña y no como cambiar de pantalla. */

.mgt-head {
  display: flex; align-items: flex-start; gap: var(--s5);
  flex-wrap: wrap; margin-bottom: var(--s4);
}
.mgt-hi {
  font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 600;
  letter-spacing: -.02em; line-height: 1.15; margin: 0;
}
/* El emoji no hereda el color del texto y en tema oscuro se veía apagado
   contra el fondo; se le deja su propio brillo y nada más. */
.mgt-wave { font-size: .9em; }
.mgt-sub { margin: var(--s2) 0 0; font-size: var(--fs-sm); color: var(--ink-3); max-width: 62ch; }

.mgt-head-side {
  display: flex; align-items: center; gap: var(--s3);
  flex-wrap: wrap; justify-content: flex-end;
}

/* Las pestañas. Fila con desbordamiento propio: son ocho y en una pantalla
   estrecha se arrastran de lado en vez de partirse en dos líneas, que dejaba
   la activa saltando de fila al cambiar de idioma. */
.mgt-tabs {
  display: flex; gap: var(--s2); margin-bottom: var(--s5);
  overflow-x: auto; scrollbar-width: none;
  border-bottom: 1px solid var(--border); padding-bottom: var(--s3);
}
.mgt-tabs::-webkit-scrollbar { display: none; }
.mgt-tab {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: 0 var(--s4); height: 38px; flex: 0 0 auto;
  border-radius: var(--r-md); border: 1px solid transparent;
  font-size: var(--fs-sm); font-weight: 500; color: var(--ink-3);
  text-decoration: none; white-space: nowrap;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.mgt-tab svg { width: 15px; height: 15px; }
.mgt-tab:hover { background: var(--surface-2); color: var(--ink-1); }
.mgt-tab.is-active {
  background: var(--primary); border-color: var(--primary);
  color: var(--on-primary, #fff); font-weight: 600;
}
.mgt-tab.is-active:hover { background: var(--primary); color: var(--on-primary, #fff); }

/* Cinco indicadores en fila, y el número de columnas es FIJO por tramo.
   Con `auto-fit` la rejilla mete las que caben y a media anchura dejaba
   cuatro arriba y la quinta sola abajo — un huérfano que se lee como que
   algo se rompió. Con tramos, las filas siempre cierran: 5, luego 3+2. */
.mgt-kpis {
  display: grid; gap: var(--s4);
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
@media (max-width: 1240px) {
  .mgt-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* La gráfica manda y el reparto la acompaña, como en el boceto. */
.mgt-split {
  display: grid; gap: var(--s5);
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  align-items: stretch;
}
.mgt-split > .card { display: flex; flex-direction: column; }

/* EL HUECO CON SU CARA.
   Un bloque sin fuente NO se deja en blanco ni se rellena con un cero: se
   pinta el `N/A` en grande, con el icono apagado, y debajo qué falta. Lo que
   se ve a un metro es que ahí no hay dato — no que el bloque se rompió. */
.mgt-gap {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4); border-radius: var(--r-md);
  background: var(--surface-2); border: 1px dashed var(--border);
}
.mgt-gap svg { width: 22px; height: 22px; color: var(--ink-4, var(--ink-3)); }
.mgt-gap-v {
  font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 600;
  color: var(--ink-3); letter-spacing: -.02em;
}

/* El ranking del top de certificaciones. */
.mgt-rank { display: flex; align-items: center; gap: var(--s3); }
.mgt-rank-n {
  display: inline-grid; place-items: center; flex: 0 0 auto;
  width: 24px; height: 24px; border-radius: 999px;
  background: var(--neutral-soft); color: var(--ink-2);
  font-size: var(--fs-2xs); font-weight: 700;
}

/* Cada alerta con su icono, su motivo y su estado. */
.mgt-alert {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); border-radius: var(--r-md); background: var(--surface-2);
}
.mgt-alert-ico {
  display: inline-grid; place-items: center; flex: 0 0 auto;
  width: 32px; height: 32px; border-radius: var(--r-sm, var(--r-md));
  background: var(--warning-soft); color: var(--warning);
}
.mgt-alert-ico svg { width: 16px; height: 16px; }

/* Una pestaña reservada y todavía vacía. Centrada y con aire: tiene que
   leerse como «aquí no hay nada TODAVÍA», no como una pantalla que falló. */
.mgt-soon { text-align: center; }
.mgt-soon .card-body { align-items: center; padding: var(--s7, var(--s5)) var(--s5); }
.mgt-soon h3 { margin: 0; }
.mgt-soon p { max-width: 52ch; }
.mgt-soon-ico {
  display: inline-grid; place-items: center;
  width: 52px; height: 52px; border-radius: var(--r-lg, var(--r-md));
  background: var(--neutral-soft); color: var(--ink-3);
}
.mgt-soon-ico svg { width: 24px; height: 24px; }

/* ============================================= KPIs DE GERENCIA ======== */
/* La pantalla sigue el diseño aprobado: tarjeta con icono en cuadro teñido,
   cifra grande, chip de variacion al lado y un pie pequeño. */

.mk-bar {
  display: flex; align-items: center; gap: var(--s3);
  flex-wrap: wrap; margin-bottom: var(--s5);
}

.kpi-card {
  display: flex; flex-direction: column; gap: var(--s2);
  padding: var(--s4) var(--s5);
}
.kpi-ico {
  display: inline-grid; place-items: center;
  width: 38px; height: 38px; border-radius: var(--r-md);
  background: var(--neutral-soft); color: var(--ink-2); margin-bottom: var(--s1);
}
.kpi-ico svg { width: 19px; height: 19px; }
.kpi-ico[data-tone="primary"] { background: var(--primary-soft); color: var(--primary); }
.kpi-ico[data-tone="teal"]    { background: var(--info-soft);    color: var(--info); }
.kpi-ico[data-tone="purple"]  { background: var(--accent-soft);  color: var(--accent); }
.kpi-ico[data-tone="amber"]   { background: var(--warning-soft); color: var(--warning); }
.kpi-ico[data-tone="success"] { background: var(--success-soft); color: var(--success); }

.kpi-label {
  font-size: var(--fs-sm); font-weight: 500; letter-spacing: 0;
  text-transform: none; color: var(--ink-3);
}
.kpi-row { display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap; }
.kpi-value {
  font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 600;
  letter-spacing: -.02em; line-height: 1.1;
}
.kpi-foot { font-size: var(--fs-2xs); color: var(--ink-3); line-height: 1.45; }

/* El chip de variacion. Verde sube, rojo baja, gris plano -- y NO se pinta
   cuando no se puede calcular, que es distinto de valer cero. */
.kpi-delta {
  font-size: var(--fs-2xs); font-weight: 600; white-space: nowrap;
  padding: 2px var(--s2); border-radius: 999px;
  background: var(--neutral-soft); color: var(--ink-3);
}
.kpi-delta[data-dir="up"]   { background: var(--success-soft); color: var(--success); }
.kpi-delta[data-dir="down"] { background: var(--danger-soft);  color: var(--danger); }

/* Dos tercios para la tabla de programas, un tercio para paises y ciudades.
 *
   `stretch` y no `start`: la columna de la derecha lleva DOS tarjetas y casi
   siempre es mas alta, asi que con alturas naturales la de programas terminaba
   a media altura y dejaba un hueco en blanco al lado. Nivelarlas es lo que hace
   que las dos columnas cierren en la misma linea.
 *
   El sobrante se lo queda la tabla --que es lo que puede crecer sin deformarse--
   en vez de repartirse entre cabecera, paginador y pie. `min-height: 0` para que
   el `overflow` de la tabla siga funcionando dentro de un flex. */
.mk-split {
  display: grid; gap: var(--s5);
  grid-template-columns: minmax(0, 1.8fr) minmax(0, 1fr);
  align-items: stretch;
}
.mk-split > .card { display: flex; flex-direction: column; }
.mk-split > .card > .table-wrap { flex: 1 1 auto; min-height: 0; }

.res-grid { display: grid; gap: var(--s3); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.res-mini {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--s3); border-radius: var(--r-md); background: var(--surface-2);
}
.res-mini .lb { font-size: var(--fs-2xs); font-weight: 600; color: var(--ink-3); }
.res-mini .vl {
  font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 600;
  letter-spacing: -.02em;
}

/* Top ciudades: numero, bandera, nombre y cifra. */
.ciu-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) 0; border-bottom: 1px solid var(--border);
}
.ciu-row:last-child { border-bottom: 0; }
.ciu-n {
  flex: none; width: 20px; text-align: center;
  font-size: var(--fs-2xs); font-weight: 600; color: var(--ink-4);
}

/* Tablas del panel: mas compactas que las de operacion, porque aqui se leen
   diez filas de un vistazo y no se trabaja fila a fila. */
/* `.table.table-tight tbody td` y no `.table-tight td`: la regla base es
   `.table tbody td`, que con una clase y dos elementos tiene MAS especificidad
   que una clase y un elemento. Escrita corta, esta regla no se aplicaba nunca
   --las celdas seguian con el relleno de siempre-- y no habia forma de notarlo
   salvo midiendo. */
.table.table-tight thead th,
.table.table-tight tbody td { padding-top: var(--s2); padding-bottom: var(--s2); }

@media (max-width: 1100px) {
  .mk-split { grid-template-columns: minmax(0, 1fr); }
}

/* La etiqueta «Sin catalogar» va en linea con el nombre del programa y NO se
   encoge: si se encogiera, un nombre largo la aplastaria hasta hacerla ilegible
   en vez de recortarse el mismo. */
.badge.t-2xs { flex: none; }

/* ==========================================================================
   JIRA
   --------------------------------------------------------------------------
   Un tablero se lee de un vistazo o no se lee. Todo aquí busca eso: las
   columnas siempre visibles, la tarjeta con lo justo, y el color reservado
   para lo que urge — si todo destaca, no destaca nada.
   ========================================================================== */

.jr-proj { max-width: 240px; min-width: 140px; }

/* --------------------------------------------------------------- tarjeta -- */

.jr-card {
  /* Ocupa el ancho de la columna: vive dentro de `.kb-cards`, que es flex
     en columna, y sin esto se encogeria al contenido. */
  width: 100%;
  padding: var(--s3) var(--s4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease),
              transform var(--t-fast) var(--ease);
}
.jr-card:hover { border-color: var(--primary); box-shadow: var(--shadow-sm); }
.jr-card.is-dragging { opacity: .45; transform: rotate(1.5deg); }
/* Lo vencido se ve sin leer, y por eso el rojo se reserva para lo que ya se
   pasó de fecha. Era una banda de 3 px a la izquierda; ahora es el borde
   entero, que se ve igual de lejos y no parte la tarjeta en dos. */
.jr-card.is-over { border-color: var(--danger); }
/* Se agarra: la tarjeta se arrastra para cambiarla de columna y para subirla o
   bajarla dentro de la suya. Mismo gesto que las del tablero de Mi espacio. */
.jr-card { cursor: grab; }
.jr-card:active { cursor: grabbing; }

/* ---- dónde va a caer la que se arrastra (0098) ----
   Una raya, no un hueco: abrir un espacio empujaría media columna con cada
   píxel que se mueve el cursor, y la tarjeta que se busca deja de estar donde
   se la vio. La raya solo dice el sitio. */
.kb-col.is-drop-col {
  background: var(--primary-soft);
  border-color: var(--primary);
  border-style: dashed;
}
.kb-cards .jr-card.is-drop-here { box-shadow: 0 -3px 0 -1px var(--primary); }
.kb-cards.is-drop-end::after {
  content: ''; display: block; flex: none;
  height: 2px; border-radius: var(--r-full); background: var(--primary);
}

.jr-card-top { display: flex; align-items: center; gap: var(--s2); margin-bottom: 6px; }
.jr-key {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .03em;
  color: var(--ink-4);
}
/* Sin negrita: en una columna de quince tarjetas, quince títulos en negrita
   no destacan ninguno --sube el peso de todo el tablero y no queda nada con
   lo que contrastar--. En la ficha abierta sí va en negrita (`.jr-issue-title`):
   allí es el único título y compite con el resto de la ficha. */
.jr-title { font-size: var(--fs-sm); font-weight: 400; line-height: 1.4; color: var(--ink); }

.jr-prio { display: inline-flex; align-items: center; gap: 4px; margin-left: auto; }
.jr-prio.tone-danger  { color: var(--danger); }
.jr-prio.tone-warning { color: var(--warning); }
.jr-prio.tone-muted   { color: var(--ink-4); }

.jr-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.jr-tag {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 1px 7px; border-radius: var(--r-full);
  background: color-mix(in srgb, var(--primary) 10%, transparent);
  color: var(--primary);
  font-size: var(--fs-2xs); font-weight: 600;
}
.jr-tag.is-more { background: var(--surface-3); color: var(--ink-4); }
.jr-x {
  border: 0; background: transparent; color: inherit; cursor: pointer;
  display: inline-flex; padding: 0; opacity: .6;
}
.jr-x:hover { opacity: 1; }

.jr-prog { display: flex; align-items: center; gap: var(--s2); margin-top: 8px; }
.jr-prog-bar {
  flex: 1; height: 5px; border-radius: var(--r-full);
  background: var(--surface-3); overflow: hidden;
}
.jr-prog-bar > span { display: block; height: 100%; background: var(--success); }
.jr-prog-n { font-size: var(--fs-2xs); color: var(--ink-4); font-weight: 600; }

.jr-card-foot { display: flex; align-items: center; gap: var(--s2); margin-top: 8px; }
.jr-due {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-2xs); color: var(--ink-4); font-weight: 600;
}
.jr-due.is-soon { color: var(--warning); }
.jr-due.is-over { color: var(--danger); }
.jr-unassigned {
  display: grid; place-items: center; width: 22px; height: 22px;
  border: 1px dashed var(--border-strong); border-radius: 50%; color: var(--ink-4);
}

/* ------------------------------------------------------------------ tipo -- */

/* El tipo de la tarea --Error, Función, Historia, Tarea-- es un cuadradito de
   color con su icono, como en JIRA: se reconoce antes de leer la clave. Cada
   tipo lleva un color distinto a propósito; en JIRA Función e Historia
   comparten el verde y a dos pasos no se distinguen. */
.jr-type {
  display: inline-grid; place-items: center; flex: none;
  width: 16px; height: 16px; border-radius: 4px;
  color: #fff; background: var(--ink-4);
}
.jr-type svg { width: 11px; height: 11px; color: inherit; stroke-width: 2.4; }
.jr-type.tone-danger  { background: var(--danger); }
.jr-type.tone-success { background: var(--success); }
.jr-type.tone-primary { background: var(--primary); }
.jr-type.tone-purple  { background: var(--brand-purple); }
/* En oscuro los tonos son pastel y el trazo blanco no contrasta: va en tinta oscura. */
[data-theme="dark"] .jr-type { color: var(--ink-invert); }
[data-theme="dark"] .jr-type.tone-purple { background: #a78bfa; }

/* El selector: un botón con la piel de `.select` --misma altura, borde y
   flecha-- porque un <option> no puede llevar icono. Abre el menú de la casa. */
.jr-type-btn { display: inline-flex; align-items: center; gap: 8px; text-align: left; line-height: normal; }
.jr-type-btn .jr-type-name {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.jr-type-pick .dropdown-menu { min-width: 100%; }
/* `.menu-item svg` recolorea y agranda cualquier icono del menú; el del tipo
   conserva su cuadradito y su blanco, también al pasar el ratón. */
.jr-type-item .jr-type svg, .jr-type-item:hover .jr-type svg { width: 11px; height: 11px; color: inherit; }
/* La prioridad dentro del selector y de su menú. `.jr-prio` nace con
   `margin-left:auto` porque en la tarjeta va pegada a la derecha; aquí abre la
   fila, así que se le quita. Y el icono conserva SU color --rojo, ámbar,
   gris--, que es justo lo que se pidió ver: `.menu-item svg` lo teñiría de
   gris en reposo y de azul al pasar por encima. */
.jr-type-btn .jr-prio, .jr-type-item .jr-prio { margin-left: 0; }
.jr-type-btn .jr-prio svg,
.jr-type-item .jr-prio svg, .jr-type-item:hover .jr-prio svg { width: 14px; height: 14px; color: inherit; }
.jr-type-item.is-active, .jr-who-item.is-active { background: var(--primary-soft); color: var(--ink); }
.menu-item .jr-menu-check, .menu-item:hover .jr-menu-check {
  width: 15px; height: 15px; margin-left: auto; color: var(--primary);
}
.jr-who-list { max-height: 264px; overflow-y: auto; min-width: 230px; }
.jr-who-item .avatar { flex: none; }
.jr-who-item .jr-unassigned svg { width: 13px; height: 13px; }

/* ------------------------------------------------------------ compositor -- */

/* El «Añadir» de la columna abre esto en su lugar, calcado de JIRA: título,
   tipo, fecha y responsable en una tarjeta, y Enter para crear. El borde azul
   es el foco de la columna entera: dice dónde se está escribiendo. */
.jr-qa {
  margin: 0 var(--s3) var(--s3);
  padding: var(--s2) var(--s3);
  background: var(--surface);
  border: 1.5px solid var(--primary);
  border-radius: var(--r-md);
  box-shadow: var(--ring);
}
.jr-qa-title {
  display: block; width: 100%; border: 0; outline: 0; background: transparent; resize: none;
  padding: 4px 0 2px; font: inherit; font-size: var(--fs-sm); font-weight: 600; line-height: 1.4;
  color: var(--ink);
}
.jr-qa-title::placeholder { color: var(--ink-4); font-weight: 500; }
.jr-qa-title:disabled { opacity: .6; }
.jr-qa-row { display: flex; align-items: center; gap: 4px; margin-top: 4px; }
.jr-qa-btn {
  display: inline-flex; align-items: center; gap: 4px; height: 28px; min-width: 28px;
  padding: 0 5px; border-radius: var(--r-sm); color: var(--ink-3);
  font-size: var(--fs-2xs); font-weight: 600;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.jr-qa-btn:hover { background: var(--surface-3); color: var(--ink); }
.jr-qa-btn.is-set { color: var(--primary); background: var(--primary-soft); }
/* Solo los iconos sueltos del botón: el del tipo va dentro de su cuadradito. */
.jr-qa-btn > .ico { width: 15px; height: 15px; }
.jr-qa-btn > .jr-qa-chev { width: 13px; height: 13px; color: var(--ink-4); }
.jr-qa-when { position: relative; display: inline-flex; }
.jr-qa-date {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; pointer-events: none; border: 0; padding: 0; margin: 0;
}
.jr-qa-send {
  margin-left: auto; display: grid; place-items: center; width: 28px; height: 28px;
  border-radius: var(--r-sm); color: var(--ink-4);
  border: 1px solid var(--border); background: var(--surface-2);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.jr-qa-send:not(:disabled) { color: var(--primary-ink); background: var(--primary); border-color: var(--primary); }
.jr-qa-send:disabled { cursor: not-allowed; }

/* ----------------------------------------------------------------- ficha -- */

.jr-desc {
  padding: var(--s4); background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--r-md);
  font-size: var(--fs-md); line-height: 1.6; max-width: 68ch;
}
.jr-people { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.jr-person {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 6px 3px 10px; border-radius: var(--r-full);
  background: var(--surface-3); font-size: var(--fs-xs); font-weight: 600;
}

.jr-subs { display: flex; flex-direction: column; gap: 6px; }
.jr-sub {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); border: 1px solid var(--border);
  border-radius: var(--r-md); background: var(--surface);
}
.jr-sub.is-done { opacity: .6; }
.jr-sub.is-done .jr-sub-title { text-decoration: line-through; }
.jr-sub-title { font-size: var(--fs-sm); font-weight: 600; }
.jr-sub-meta { display: flex; align-items: center; gap: var(--s2); margin-top: 3px; flex-wrap: wrap; }

/* -------------------------------------------------- cabecera y pestañas -- */

/* El encabezado del proyecto, como el del espacio en JIRA: el escudo, el
   nombre en grande y, pegadas debajo, las cinco vistas. Van juntos en un solo
   bloque con una línea al pie porque son una sola cosa —«dónde estoy y cómo lo
   miro»— y separarlos dejaría las pestañas flotando sobre el contenido. */
.jr-head { margin-bottom: var(--s5); }
.jr-head-top {
  display: flex; align-items: center; gap: var(--s4);
  flex-wrap: wrap; margin-bottom: var(--s4);
}
/* Los tres controles --selector, «Nuevo proyecto», «Nueva tarea»-- en una
   sola fila y pegados a la derecha. Con `flex-wrap: wrap` el bloque se
   encogía a su ancho intrínseco y el tercer botón caía a una segunda línea
   aunque sobrara medio tablero de sitio; quien lo mira lee dos filas de
   botones desalineadas. El selector es el que cede, hasta 140 px. */
.jr-head-top .actions {
  display: flex; align-items: center; gap: var(--s2);
  flex-wrap: nowrap; justify-content: flex-end;
}
.jr-head-top .actions .btn { white-space: nowrap; }
.jr-head-name {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  font-size: var(--fs-2xl); letter-spacing: -.028em;
}
/* El escudo con las dos primeras letras de la clave. Es lo que distingue dos
   tableros de un vistazo, antes de leer el nombre. */
.jr-shield {
  flex: none; display: grid; place-items: center;
  width: 48px; height: 48px; border-radius: var(--r-md);
  color: #fff; font-family: var(--font-display);
  font-size: var(--fs-lg); font-weight: 700; letter-spacing: -.01em;
}
.jr-shield.is-empty { background: var(--surface-3); color: var(--ink-4); }
/* El escudo dentro de la ficha va pequeño: allí es una miga de pan, no un
   título. */
.crumbs .jr-shield { width: 20px; height: 20px; border-radius: var(--r-xs); font-size: var(--fs-3xs); }
.jr-tabs { margin-bottom: var(--s5); }

/* ---------------------------------------------------------------- resumen -- */

/* La actividad reciente se queda en su alto y se desplaza dentro: diez líneas
   estiraban la tarjeta hasta el doble que la de al lado, y una fila de dos
   tarjetas con una al doble de alto que la otra se lee como un error. */
.jr-feed {
  display: flex; flex-direction: column;
  max-height: 330px; overflow-y: auto;
  /* Hueco para la barra de desplazamiento: sin el, la hora relativa de la
     derecha --«ayer»-- queda medio tapada por ella en pantalla estrecha. */
  padding-right: var(--s2);
}
.jr-feed-item {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3) 0; border-bottom: 1px solid var(--border-soft);
}
.jr-feed-item:last-child { border-bottom: 0; padding-bottom: 0; }
.jr-feed-key {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 3px;
  max-width: 100%; color: var(--ink-3); font-size: var(--fs-xs);
  transition: color var(--t-fast) var(--ease);
}
.jr-feed-key:hover { color: var(--primary); }
.jr-feed-key:hover .jr-key { color: var(--primary); }

.jr-mini { display: flex; flex-direction: column; gap: 2px; }
.jr-mini-row {
  display: flex; align-items: center; gap: var(--s2); width: 100%;
  padding: var(--s2) var(--s3); border-radius: var(--r-md); text-align: left;
  transition: background var(--t-fast) var(--ease);
}
.jr-mini-row:hover { background: var(--surface-2); }

/* ------------------------------------------------------------------ lista -- */

/* La tabla no se encoge por debajo de su ancho util: con ocho columnas en una
   pantalla estrecha, repartir el hueco a la fuerza deja el desplegable de
   estado convertido en una flecha sin texto. Antes se desplaza. */
.jr-list { min-width: 1020px; }
.jr-list th { white-space: nowrap; }
.jr-list td { vertical-align: middle; }
.jr-list td:first-child { width: 30%; }
.jr-list td:nth-child(3) { white-space: nowrap; }
.jr-li-cell { display: flex; align-items: center; gap: 4px; min-width: 0; }
.jr-li-caret {
  flex: none; display: grid; place-items: center; width: 20px; height: 20px;
  border-radius: var(--r-xs); color: var(--ink-4);
  transition: transform var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.jr-li-caret:hover { background: var(--surface-3); color: var(--ink); }
.jr-li-caret.is-open { transform: rotate(90deg); }
.jr-li-caret.is-empty { pointer-events: none; }
.jr-li-open {
  display: inline-flex; align-items: center; gap: var(--s2); min-width: 0;
  max-width: 46ch; text-align: left; font-size: var(--fs-sm); color: var(--ink);
  transition: color var(--t-fast) var(--ease);
}
.jr-li-open:hover { color: var(--primary); }
.jr-li-open:hover .jr-key { color: var(--primary); }
/* Lo terminado se tacha en la clave, no en el título: el título hay que poder
   leerlo, y la clave tachada ya dice que eso está cerrado. */
.jr-li-open.is-done .jr-key { text-decoration: line-through; opacity: .7; }
.jr-li-n {
  flex: none; padding: 0 6px; border-radius: var(--r-full);
  background: var(--surface-3); color: var(--ink-4);
  font-size: var(--fs-2xs); font-weight: 700;
}
.jr-li-who { display: inline-flex; align-items: center; gap: 6px; min-width: 0; font-size: var(--fs-sm); }
.jr-li-status {
  min-width: 124px; height: 30px; line-height: 28px; padding: 0 28px 0 10px;
  font-size: var(--fs-xs); font-weight: 600; background-position: right 6px center;
}
/* La subtarea entra sangrada y con la fila un punto más apagada: se lee que
   cuelga de la de arriba sin necesidad de una línea que las una. */
.jr-li-subrow > td { background: var(--surface-2); }
.jr-li-subrow > td:first-child { padding-left: var(--s7); }

/* ------------------------------------------------------------- cronograma -- */

.jr-tl-scroll { overflow-x: auto; }
.jr-tl-grid { min-width: 760px; }
.jr-tl-head, .jr-tl-row, .jr-tl-overlay {
  display: grid; grid-template-columns: var(--tl-left) minmax(0, 1fr);
}
.jr-tl-head {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.jr-tl-months { display: flex; }
.jr-tl-months > span {
  flex: none; padding: var(--s3) var(--s2);
  border-left: 1px solid var(--border-soft);
  font-size: var(--fs-2xs); font-weight: 700; color: var(--ink-4);
  text-transform: uppercase; letter-spacing: .04em;
}
.jr-tl-body { position: relative; }
.jr-tl-overlay { position: absolute; inset: 0; pointer-events: none; }
.jr-tl-lane { position: relative; }
.jr-tl-today { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--danger); opacity: .5; }
.jr-tl-row { border-bottom: 1px solid var(--border-soft); }
.jr-tl-row:last-child { border-bottom: 0; }
.jr-tl-name {
  display: flex; align-items: center; gap: 6px; min-width: 0;
  padding: var(--s3) var(--s4); text-align: left;
  border-right: 1px solid var(--border);
}
.jr-tl-name:hover { background: var(--surface-2); }
.jr-tl-name.is-head {
  font-size: var(--fs-2xs); font-weight: 700; color: var(--ink-4);
  text-transform: uppercase; letter-spacing: .04em;
}
.jr-tl-track { position: relative; height: 44px; }
.jr-tl-bar {
  position: absolute; top: 50%; transform: translateY(-50%);
  height: 24px; min-width: 6px; border-radius: var(--r-sm);
  background: var(--primary); display: flex; align-items: center; overflow: hidden;
}
.jr-tl-bar.is-done { background: var(--success); }
.jr-tl-bar.is-over { background: var(--danger); }
.jr-tl-bar-in {
  padding: 0 8px; color: #fff; font-size: var(--fs-2xs); font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Lo que no tiene fecha límite sale como un punto en el día que se creó: una
   barra le inventaría un final que nadie decidió. */
.jr-tl-dot {
  position: absolute; top: 50%; width: 10px; height: 10px; margin-left: -5px;
  transform: translateY(-50%) rotate(45deg);
  background: var(--surface-3); border: 1px solid var(--border-strong);
}

/* ------------------------------------------------------------------ ficha -- */

/* La ficha se pega a los bordes del modal: la cabecera y las dos columnas
   ponen su propio espaciado, y el del modal dejaría un marco alrededor de una
   cabecera que debe llegar de lado a lado. */
.modal-body:has(> .jr-issue) { padding: 0; }

.jr-issue-head {
  position: sticky; top: 0; z-index: 2;
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s4) var(--s5);
  background: var(--surface); border-bottom: 1px solid var(--border-soft);
}
.jr-issue-head .crumbs { margin-bottom: 0; min-width: 0; font-size: var(--fs-sm); }
.jr-issue-head .icon-btn[data-del-issue]:hover { color: var(--danger); background: var(--danger-soft); }
.jr-issue-cols {
  display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr);
  gap: var(--s5); padding: var(--s5);
}
.jr-issue-main { min-width: 0; }
.jr-issue-side { display: flex; flex-direction: column; gap: var(--s4); align-self: start; }

/* El título se edita donde se lee. Sin borde hasta que se toca: un campo de
   formulario ahí arriba haría que la ficha pareciera un formulario. */
.jr-issue-title {
  display: block; width: 100%; resize: none; overflow: hidden;
  margin-bottom: var(--s5); padding: 4px 8px; margin-left: -8px;
  border: 1px solid transparent; border-radius: var(--r-sm);
  background: transparent; color: var(--ink);
  font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 650;
  line-height: 1.25; letter-spacing: -.02em;
}
.jr-issue-title:hover { background: var(--surface-2); }
.jr-issue-title:focus { background: var(--surface); border-color: var(--primary); outline: none; }
.jr-issue-h {
  display: flex; align-items: center; gap: var(--s2);
  margin: var(--s5) 0 var(--s3);
  font-size: var(--fs-sm); font-weight: 700; color: var(--ink-2);
}
.jr-issue-h:first-of-type { margin-top: 0; }
.jr-issue-h-n {
  padding: 1px 7px; border-radius: var(--r-full);
  background: var(--surface-3); color: var(--ink-4);
  font-size: var(--fs-2xs); font-weight: 700;
}
.jr-desc.is-empty { color: var(--ink-4); }
.jr-desc[data-desc-view] { cursor: text; transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease); }

/* ---- «esto se edita» (4-sep-2026) ----
   El título y la descripción se editan donde se leen, y hasta hoy nada lo
   decía: había que probar a hacer clic. Ahora al pasar por encima el bloque se
   apaga a gris y asoma un lápiz en la esquina. El lápiz NO está siempre: un
   icono fijo en cada campo llena la ficha de ruido y deja de significar nada.

   El lápiz vive fuera del campo --hermano, no hijo-- porque el título y el
   cuadro de escribir son `<textarea>`, y un textarea no puede tener nada
   dentro. Por eso `.jr-editable` es quien tiene la posición. */
.jr-editable { position: relative; }
.jr-pen {
  position: absolute; top: 8px; right: 8px;
  display: inline-flex; pointer-events: none;
  color: var(--ink-4); opacity: 0;
  transition: opacity var(--t-fast) var(--ease);
}
.jr-pen svg { width: 14px; height: 14px; }
.jr-editable:hover > .jr-pen,
.jr-editable:focus-within > .jr-pen { opacity: 1; }

.jr-editable:hover > .jr-issue-title,
.jr-editable:hover > .jr-desc[data-desc-view] {
  background: var(--surface-3);
  border-color: var(--border-strong);
}
/* En el título, al escribir manda el campo enfocado: fondo limpio y borde
   azul, que es como se ve cualquier otro campo de la casa cuando está activo. */
.jr-issue-title:focus { background: var(--surface); }

/* La descripción NO: al pulsar se queda con el mismo gris que tenía leyéndose
   --el cuadro no cambia de aspecto al tocarlo, solo se vuelve escribible-- y
   el lápiz se queda fijo, porque ahí ya no hay que anunciar nada: se está
   editando. El texto de dentro también sigue siendo el mismo, «Añadir una
   descripción»; antes cambiaba a otra frase al pulsar y parecía otro campo. */
.jr-desc-ta { background: var(--surface-2); }
.jr-desc-ta:focus { background: var(--surface-2); border-color: var(--primary); }
.jr-desc-edit .jr-pen { opacity: 1; }

/* La lista de personas del panel de detalles: la misma del compositor, con
   buscador porque aquí caben todos menos los que ya están. */
.jr-who-pick { display: flex; flex-direction: column; gap: var(--s2); min-width: 250px; }
.jr-who-q { height: 32px; font-size: var(--fs-sm); }
.jr-who-role { display: block; font-size: var(--fs-2xs); color: var(--ink-4); font-weight: 500; }
.jr-who-none { padding: var(--s3); font-size: var(--fs-sm); color: var(--ink-4); text-align: center; }

/* Los adjuntos (0092). Las imágenes en rejilla porque se miran, y todo lo
   demás en fila porque se abre: una miniatura de un CSV es un rectángulo gris
   que no dice nada. */
.jr-atts { display: flex; flex-wrap: wrap; gap: var(--s3); }
.jr-atts:empty { display: none; }
.jr-att {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); border: 1px solid var(--border);
  border-radius: var(--r-md); background: var(--surface);
  width: 100%;
}
.jr-att-name { font-size: var(--fs-sm); font-weight: 600; display: block; }
.jr-att-size { font-size: var(--fs-2xs); color: var(--ink-4); }
.jr-att-ico { display: flex; color: var(--ink-4); flex: none; }
.jr-att-note { display: block; font-size: var(--fs-2xs); color: var(--ink-4); }
.jr-att.is-pending { opacity: .7; }

/* La imagen: 160 px de ancho es lo que hace que una captura de pantalla se
   reconozca sin abrirla y que quepan cuatro por fila. */
.jr-att-img { width: 160px; padding: 0; overflow: hidden; flex-direction: column; align-items: stretch; }
.jr-att-img > a { display: block; position: relative; line-height: 0; }
.jr-att-img img { width: 100%; height: 110px; object-fit: cover; display: block; }
.jr-att-img figcaption {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s3); border-top: 1px solid var(--border); min-width: 0;
}
.jr-att-img figcaption > .grow, .jr-att-img figcaption .jr-att-name { min-width: 0; }

/* El hueco mientras se firma la URL. El bucket es privado, así que la imagen
   no existe hasta que vuelve la firma; sin esto se vería la caja rota. */
.jr-att-ph {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 110px; background: var(--surface-3); color: var(--ink-4);
}
.jr-att-ph.is-failed { background: var(--danger-soft); color: var(--danger); }
.jr-att-del:hover { color: var(--danger); background: var(--danger-soft); }

/* Arrastrar y soltar (3-sep-2026). La zona es todo el bloque de adjuntos, pero
   quien suelta apunta a la ficha entera: el resalte solo dice DÓNDE va a caer,
   no dónde hay que apuntar. Sin borde permanente --un recuadro punteado fijo
   es ruido las 23 horas del día en que nadie arrastra nada--, solo la frase
   al lado del botón. */
.jr-att-drop { position: relative; border-radius: var(--r-md); }
.jr-att-acts { display: flex; align-items: center; gap: var(--s3); margin-top: var(--s2); flex-wrap: wrap; }
.jr-att-hint { font-size: var(--fs-2xs); color: var(--ink-4); }
.jr-att-veil {
  position: absolute; inset: calc(var(--s2) * -1); display: none;
  align-items: center; justify-content: center; gap: var(--s2);
  border: 2px dashed var(--primary); border-radius: var(--r-md);
  background: var(--primary-soft); color: var(--primary);
  font-size: var(--fs-sm); font-weight: 600; pointer-events: none;
}
.jr-att-drop.is-over .jr-att-veil { display: flex; }
.jr-att-drop.is-busy { opacity: .6; pointer-events: none; }

/* ---------------------------------------------- Carga masiva (0114) ----- */
/* La zona de soltar SÍ lleva borde punteado permanente, al revés que la de los
   adjuntos: aquí es lo único que hay en el cuadro, y sin recuadro el botón
   «Elegir archivo» flota en medio de la nada sin decir que también se puede
   arrastrar. */
.jr-imp-drop {
  display: flex; flex-direction: column; align-items: center; gap: var(--s2);
  padding: var(--s6) var(--s5); text-align: center;
  border: 2px dashed var(--border-strong); border-radius: var(--r-lg);
  background: var(--surface-2);
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.jr-imp-drop.is-over { border-color: var(--primary); background: var(--primary-soft); }
.jr-imp-ico { color: var(--ink-4); }
.jr-imp-drop.is-over .jr-imp-ico { color: var(--primary); }
.jr-imp-lead { font-size: var(--fs-md); font-weight: 600; color: var(--ink); }
.jr-imp-sub { font-size: var(--fs-xs); color: var(--ink-4); }
.jr-imp-drop .btn { margin-top: var(--s2); }

.jr-imp-help { margin-top: var(--s4); font-size: var(--fs-sm); color: var(--ink-3); }
.jr-imp-help p + p, .jr-imp-help .btn { margin-top: var(--s2); }
.jr-imp-cols { font-size: var(--fs-xs); color: var(--ink-4); }

.jr-imp-sum {
  display: flex; align-items: center; gap: var(--s2);
  flex-wrap: wrap; margin-bottom: var(--s3);
}
.jr-imp-sum .btn { margin-left: auto; }
.jr-imp-sum + .alert { margin-bottom: var(--s3); }

/* La vista previa se desplaza dentro del cuadro y no lo estira: con ochenta
   filas, un modal que crece deja el botón «Crear» fuera de la pantalla. */
.jr-imp-table { max-height: 48vh; overflow: auto; }
.jr-imp-table th { position: sticky; top: 0; z-index: 1; background: var(--surface); }

/* Un aviso NO tacha la fila: la tarea se va a crear igual, solo que sin
   responsable o con la prioridad por defecto. Lo que se ignora es la fila
   `is-bad`, y esa sí se apaga. */
.jr-imp-warn {
  display: block; margin-top: 3px;
  font-size: var(--fs-2xs); font-weight: 500; color: var(--warning);
}
.jr-imp-bad td { opacity: .65; }
.jr-imp-bad .jr-imp-warn { display: inline; color: var(--danger); }

/* El filtro de la actividad se hacía con el atributo `hidden` y no se veía:
   `.jr-act { display: flex }` es una regla de autor y le gana a la del
   navegador para `[hidden]`, así que las filas ocultas seguían pintándose y
   las tres pestañas mostraban lo mismo. */
.jr-act[hidden] { display: none; }

/* La actividad, con sus tres pestañas: mezclar treinta cambios de estado con
   dos comentarios esconde los dos comentarios. */
.jr-act-tabs { display: flex; gap: 4px; margin-bottom: var(--s3); }
.jr-act-tab {
  padding: 5px 12px; border-radius: var(--r-full);
  border: 1px solid var(--border); background: var(--surface);
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink-3);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.jr-act-tab:hover { background: var(--surface-2); color: var(--ink); }
.jr-act-tab.is-active { background: var(--primary-soft); border-color: var(--primary); color: var(--primary); }
.jr-note-box { display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s4); }
.jr-acts { display: flex; flex-direction: column; gap: var(--s3); }
.jr-act { display: flex; align-items: flex-start; gap: var(--s3); }
.jr-act-top { display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap; }
.jr-act-body { display: flex; align-items: center; gap: 6px; margin-top: 2px; }
.jr-act-body svg { width: 13px; height: 13px; flex: none; }
/* El comentario va en globo y el cambio de estado no: uno lo escribió una
   persona y el otro lo anotó el sistema. */
.jr-act.is-note .jr-act-body {
  display: block; margin-top: 5px; padding: var(--s3);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-md); font-size: var(--fs-sm); line-height: 1.5;
}

/* El estado, arriba del panel y con el color de su columna. */
.jr-status {
  width: 100%; font-weight: 700; color: var(--jr-st, var(--ink));
  border-color: color-mix(in srgb, var(--jr-st, var(--border)) 45%, var(--border));
  background-color: color-mix(in srgb, var(--jr-st, var(--surface)) 10%, var(--surface));
}

.jr-panel { border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface-2); }
.jr-panel-head {
  display: flex; align-items: center; gap: 6px; width: 100%;
  padding: var(--s3) var(--s4); text-align: left;
  font-size: var(--fs-sm); font-weight: 700; color: var(--ink-2);
}
.jr-panel-head svg { transition: transform var(--t-fast) var(--ease); }
.jr-panel.is-closed .jr-panel-head svg { transform: rotate(-90deg); }
.jr-panel.is-closed .jr-panel-body { display: none; }
.jr-panel-body {
  display: flex; flex-direction: column; gap: var(--s3);
  padding: 0 var(--s4) var(--s4);
}
.jr-row { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: var(--s2); align-items: center; }
.jr-row-k { font-size: var(--fs-xs); color: var(--ink-3); }
.jr-row-v { min-width: 0; }
.jr-stamp {
  display: flex; flex-direction: column; gap: 2px;
  font-size: var(--fs-2xs); color: var(--ink-4);
}

@media (max-width: 900px) {
  .jr-issue-cols { grid-template-columns: minmax(0, 1fr); }
  .jr-issue-side { order: -1; }
  /* En pantalla estrecha sí se parten en dos filas: mantenerlos en una sola
     dejaría el selector de proyecto en 48 px, que no es un selector. */
  .jr-head-top .actions { flex-wrap: wrap; }
}

/* ==========================================================================
   Tecnología · Dashboard  (#/ti/dashboard)
   --------------------------------------------------------------------------
   Casi todo lo pinta la casa: `card`, `stat`, `table`, `progress` y el feed de
   JIRA. Aquí solo vive lo que esta pantalla no comparte con ninguna otra.
   ========================================================================== */

/* El recordatorio de que esto no lo ve el equipo. Va bajo el encabezado, en
   tinta apagada: es una nota al pie, no un aviso. */
.itd-scope {
  display: flex; align-items: center; gap: 6px;
  margin: calc(var(--s3) * -1) 0 var(--s5);
  font-size: var(--fs-2xs); color: var(--ink-4);
}
.itd-scope svg { flex: none; }

/* Una tarea en una línea. Es la fila del bloque de atascadas y la de las
   listas que se abren desde Higiene: la misma pieza en los dos sitios porque
   se pulsan igual y abren lo mismo. */
.itd-list { display: flex; flex-direction: column; gap: 2px; }
.itd-row {
  display: flex; align-items: center; gap: var(--s2); width: 100%;
  padding: var(--s2) var(--s3); border-radius: var(--r-md); text-align: left;
  transition: background var(--t-fast) var(--ease);
}
.itd-row:hover { background: var(--surface-2); }
/* La clave no se parte: «TI-3» en dos líneas deja de leerse como una clave. */
.itd-row .jr-key { flex: none; }

/* La carga del equipo es una tabla de cinco columnas y lo de al lado una lista
   de una: partir la fila por la mitad dejaba a la tabla con 60 px de menos de
   los que necesita y a la lista con 60 de sobra. */
.itd-split { display: grid; gap: var(--s5); grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); }

/* Carga del equipo. La tabla no se encoge por debajo de su ancho útil: con
   cinco columnas en pantalla estrecha, repartir el hueco a la fuerza deja los
   números pegados al nombre. Antes se desplaza. */
.itd-table { min-width: 420px; }
/* Cinco columnas en media tarjeta: con el relleno de tabla de la casa se
   desbordaba por 70 px y la última quedaba tras un desplazamiento que nadie
   busca en un panel. */
.itd-table th, .itd-table td { padding-left: var(--s2); padding-right: var(--s2); }
.itd-who { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.itd-who svg { flex: none; }
.itd-who .t-clip { min-width: 0; }
/* La columna del nombre absorbe el hueco que sobra y es la que se recorta
   cuando falta: los números no pueden encogerse sin dejar de leerse, y un
   nombre a medias con puntos suspensivos sigue diciendo de quién es la fila. */
/* `max-width: 0` con `width: 100%` es lo que hace que una celda de tabla
   ceda: sin él, la columna se planta en el ancho del nombre más largo y son
   los números los que se van tras un desplazamiento horizontal. */
.itd-table th:first-child, .itd-table td:first-child { width: 100%; max-width: 0; min-width: 148px; }
.itd-bad { color: var(--danger); font-weight: 600; }
/* El número y su barra, en la misma celda: la barra sola no dice cuántas son
   y el número solo no deja comparar dos filas de un vistazo. */
.itd-load { display: flex; align-items: center; gap: var(--s2); min-width: 84px; }
.itd-load .progress { flex: 1; }
/* El reloj (0112) va a ancho completo y con dos columnas de duracion escrita
   --«2 d 3 h»--, que no se pueden partir en dos lineas sin dejar de leerse de
   un vistazo. Por eso pide mas ancho que la de carga antes de desplazarse. */
.itd-time { min-width: 560px; }
.itd-time .jr-feed-key { gap: var(--s2); }
/* La barra de la mediana necesita sitio para decir algo: en 84 px --el ancho
   de la de carga, que va en media tarjeta-- queda en un guion. */
.itd-time .itd-load { min-width: 148px; }

/* Proyectos */
.itd-projs { display: flex; flex-direction: column; gap: 2px; }
.itd-proj {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) var(--s3); border-radius: var(--r-md);
  transition: background var(--t-fast) var(--ease);
}
.itd-proj:hover { background: var(--surface-2); }
.itd-proj.is-on { background: var(--primary-soft); }
.itd-proj-key {
  display: inline-grid; place-items: center; flex: none;
  min-width: 40px; height: 22px; padding: 0 6px; border-radius: var(--r-xs);
  color: #fff; font-family: var(--font-mono, ui-monospace, monospace);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .03em;
}
/* La columna del medio en flex: `.progress` es un <span> sin `display`, o sea
   en línea, y en línea no tiene ni ancho ni alto --la barra se pintaba con
   0 px--. Dentro de un contenedor flex sí se bloquifica. */
.itd-proj > .grow { display: flex; flex-direction: column; gap: 5px; }
.itd-proj-end { flex: none; min-width: 66px; text-align: right; }

/* La clave tampoco se parte en el rastro: es una etiqueta, no una frase. */
.itd-view .jr-feed-key .jr-key { flex: none; }

/* Higiene. Cada línea es un botón; la que está en cero se apaga y deja de
   pulsarse, porque abrir una lista vacía no responde ninguna pregunta. */
.itd-checks { display: flex; flex-direction: column; gap: 2px; }
.itd-check {
  display: flex; align-items: center; gap: var(--s3); width: 100%;
  padding: var(--s2) var(--s3); border-radius: var(--r-md); text-align: left;
  transition: background var(--t-fast) var(--ease);
}
.itd-check:hover:not(:disabled) { background: var(--surface-2); }
.itd-check:disabled { opacity: .6; cursor: default; }
.itd-check > svg:last-child { flex: none; color: var(--ink-4); }
.itd-check:disabled > svg:last-child { visibility: hidden; }
.itd-check-ico {
  display: inline-grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: var(--r-sm);
}
.itd-check-ico[data-tone="warn"] { background: var(--warning-soft); color: var(--warning); }
.itd-check-ico[data-tone="ok"]   { background: var(--success-soft); color: var(--success); }

@media (max-width: 900px) {
  .itd-scope { margin-top: 0; }
  .itd-split { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   Encuestas · la pantalla cuando no hay nada que responder
   --------------------------------------------------------------------------
   Rehecha el 4-sep-2026 con el diseño que mandó Juan. Es la pantalla que se ve
   el 95 % de los días —las encuestas se lanzan cada varios meses—, así que se
   trata como una página y no como el hueco entre dos lanzamientos.

   TODO el color sale de los tokens. La ilustración es un SVG sin un solo color
   escrito dentro (ver `views/surveys.js`): sus piezas se pintan desde aquí, y
   por eso funciona igual en claro y en oscuro sin escribir el dibujo dos veces.
   ========================================================================== */

.svy-hero {
  position: relative;
  overflow: hidden;                 /* recorta las dos manchas del fondo */
  border-radius: var(--r-2xl);
}

/* Las dos manchas de color del fondo. Van en pseudoelementos y no en el SVG
   porque son del LIENZO, no del dibujo: tienen que crecer con la tarjeta.
   `border-radius: 50%` + desenfoque = la mancha orgánica del diseño. */
.svy-hero::before,
.svy-hero::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  filter: blur(48px);
  pointer-events: none;
  z-index: 0;
}
.svy-hero::before {                 /* verde, arriba a la derecha */
  width: 340px; height: 300px;
  top: -130px; right: -110px;
  background: var(--success-soft);
}
.svy-hero::after {                  /* azul, abajo a la izquierda */
  width: 420px; height: 340px;
  bottom: -160px; left: -140px;
  background: var(--primary-soft);
}

.svy-hero-body {
  position: relative;               /* por encima de las manchas */
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--s10) var(--s6) var(--s8);
}

.svy-il { width: min(380px, 90%); height: auto; display: block; }

/* --- Las piezas del dibujo ------------------------------------------------
   El portapapeles es una superficie de la interfaz, no un papel blanco: usa
   `--surface` y en oscuro se oscurece con todo lo demás en vez de quemar. */
.svy-il-board    { fill: var(--surface); stroke: var(--border); stroke-width: 2.5; }
/* La sombra va en el grupo y no en cada pieza: sobre el `rect` solo, el clip
   oscuro se quedaba plano encima. */
.svy-il { filter: drop-shadow(0 12px 24px rgba(20, 26, 51, .07)); }
/* El clip va OSCURO, como en el diseño: es lo único del dibujo que no es papel
   ni tinta azul, y es lo que hace que se lea «portapapeles» y no «hoja». */
.svy-il-clip     { fill: var(--ink-4); }
.svy-il-clip-dot { fill: var(--ink-4); }
.svy-il-line     { fill: var(--primary); opacity: .16; }
.svy-il-line-soft{ opacity: .1; }
.svy-il-badge    { fill: var(--primary); }
.svy-il-check    { fill: none; stroke: var(--primary-ink); stroke-width: 3.4; stroke-linecap: round; stroke-linejoin: round; }
.svy-il-plane    { fill: var(--primary); opacity: .85; }
.svy-il-plane2   { fill: var(--primary); }   /* la cara doblada, más oscura */
.svy-il-trail    { fill: none; stroke: var(--primary); stroke-width: 2.5; stroke-linecap: round;
                   stroke-dasharray: 1 9; opacity: .45; }
.svy-il-spark    { fill: var(--warning); opacity: .7; }
.svy-il-dash     { fill: none; stroke: var(--primary); stroke-width: 3; stroke-linecap: round; opacity: .35; }

/* --- El titular ----------------------------------------------------------- */
.svy-hero-t {
  margin: var(--s5) 0 0;
  font-family: var(--font-display);
  font-size: clamp(26px, 3.6vw, 38px);
  line-height: 1.15;
  letter-spacing: -.02em;
  color: var(--ink);
}
.svy-hl { color: var(--primary); }

.svy-hero-s {
  margin: var(--s3) 0 0;
  font-size: var(--fs-md);
  color: var(--ink-3);
  max-width: 46ch;
}

/* --- Las tres razones -----------------------------------------------------
   `auto-fit` y no tres columnas fijas: a 375 px caen una debajo de otra sin
   una consulta de medios propia. */
.svy-feats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: var(--s5);
  width: 100%;
  max-width: 820px;
  margin-top: var(--s8);
  text-align: left;
}
.svy-feat { display: flex; align-items: center; gap: var(--s3); }
.svy-feat-ico {
  flex: none;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: var(--r-lg);
  background: var(--primary-soft);
  color: var(--primary);
}
.svy-feat-ico[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.svy-feat-t { font-size: var(--fs-sm); font-weight: 600; color: var(--ink); }
.svy-feat-s { font-size: var(--fs-xs); color: var(--ink-4); margin-top: 2px; }

/* --- La frase del final --------------------------------------------------- */
.svy-quote {
  width: 100%;
  max-width: 820px;
  margin: var(--s8) 0 0;
  padding-top: var(--s6);
  border-top: 1px solid var(--border-soft);
  font-size: var(--fs-sm);
  font-style: italic;
  color: var(--ink-4);
}

/* --- «¿Tienes dudas?» ----------------------------------------------------- */
.svy-help { border-radius: var(--r-full); }
.svy-faq + .svy-faq { margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--border-soft); }
.svy-faq-q { font-size: var(--fs-sm); font-weight: 600; color: var(--ink); }
.svy-faq-a { margin: var(--s1) 0 0; font-size: var(--fs-sm); color: var(--ink-3); }

@media (max-width: 640px) {
  .svy-hero-body { padding: var(--s7) var(--s4) var(--s6); }
  .svy-feats { margin-top: var(--s6); gap: var(--s4); }
  .svy-quote { margin-top: var(--s6); padding-top: var(--s5); }
}

/* --- Mi Cuenta · Sesiones activas (0103) ---------------------------------- */
.sess-row { align-items: flex-start; }
.sess-ico {
  flex: none;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: var(--r-lg);
  background: var(--surface-3);
  color: var(--ink-3);
}
/* El dispositivo desde el que se está mirando se reconoce por el color del
   icono además de por la etiqueta: la etiqueta hay que leerla. */
.sess-ico.is-me { background: var(--success-soft); color: var(--success); }
.sess-row .ds.t-xs { margin-top: 2px; font-size: var(--fs-xs); color: var(--ink-4); }

/* ==========================================================================
   JIRA · la barra de filtros, en una sola fila
   --------------------------------------------------------------------------
   Rehecha el 4-sep-2026 (Juan). Antes ocupaba dos filas: la de arriba con los
   filtros y otra entera con una pastilla por cada etiqueta —nueve en
   BadgeClaimed, y creciendo—. Las etiquetas se fueron dentro de su propio
   desplegable: son un filtro que se usa de vez en cuando, no un índice que
   haya que tener siempre delante.
   ========================================================================== */

.jr-filters { flex-wrap: wrap; align-items: center; gap: var(--s2); }

/* --- Personal / Equipo ----------------------------------------------------
   El activo va en AZUL sobre azul claro y no en blanco sobre gris: en una
   barra con tres desplegables al lado, el blanco sobre gris no se distingue
   de un botón cualquiera y había que leer los dos para saber cuál estaba. */
.jr-seg { flex: none; }
.jr-seg button { gap: var(--s2); font-weight: 500; }
.jr-seg button.is-active {
  background: var(--primary-soft);
  color: var(--primary);
  font-weight: 600;
  box-shadow: none;
}
.jr-seg button.is-active svg { color: var(--primary); }

/* --- Los tres desplegables ------------------------------------------------ */
.jr-fl {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  width: auto;
  padding-right: var(--s2);
  white-space: nowrap;
}
.jr-fl-lb { color: var(--ink-4); font-size: var(--fs-xs); }
.jr-fl-val { color: var(--ink); font-weight: 500; }
.jr-fl-ico { color: var(--ink-4); flex: none; }
.jr-fl-chev { color: var(--ink-4); margin-left: auto; flex: none; }
.jr-fl-chev.is-on { color: var(--primary); }
/* Un filtro puesto se ve sin leerlo: es lo que responde «¿por qué veo tan
   pocas tarjetas?», que es la pregunta que se hace mirando esta barra. */
.jr-fl.is-on { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.jr-fl.is-on .jr-fl-lb { color: var(--ink-3); }

/* --- La caja de búsqueda --------------------------------------------------
   La lupa va DENTRO, así que el `<input>` deja hueco a la izquierda y la
   etiqueta hace de marco: el foco se pinta sobre la etiqueta y no sobre el
   campo, o el borde saldría por dentro del recuadro. */
.jr-search {
  position: relative;
  display: flex;
  align-items: center;
  /* Crece con lo que sobre, pero cede primero que nadie: el que se quedaba
     fuera de la fila al encoger era «Ver archivadas», y un filtro que salta de
     sitio segun el ancho de la ventana no se encuentra dos veces igual. */
  flex: 1 1 180px;
  max-width: 420px;
  min-width: 150px;
}
.jr-search > svg {
  position: absolute;
  left: var(--s3);
  color: var(--ink-4);
  pointer-events: none;
}
.jr-search .input { padding-left: 36px; padding-right: 32px; width: 100%; }
.jr-search-x {
  position: absolute;
  right: 6px;
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  border: 0; border-radius: var(--r-full);
  background: transparent;
  color: var(--ink-4);
  cursor: pointer;
}
.jr-search-x:hover { background: var(--surface-3); color: var(--ink-2); }

/* --- El menú de etiquetas ------------------------------------------------- */
.jr-tag-pick { width: 260px; display: flex; flex-direction: column; }
.jr-tag-q { margin: var(--s2); width: calc(100% - var(--s4)); }
.jr-tag-list { max-height: 240px; overflow-y: auto; }
.jr-tag-none { margin: 0; padding: var(--s4); text-align: center; font-size: var(--fs-xs); color: var(--ink-4); }
.jr-tag-item { gap: var(--s2); }
/* La casilla: el visto vive dentro y solo se ve cuando está marcada. Así el
   alto de la fila no cambia al marcar, que es lo que hace saltar la lista. */
.jr-tag-box {
  flex: none;
  width: 16px; height: 16px;
  display: grid; place-items: center;
  border: 1.5px solid var(--border-strong);
  border-radius: var(--r-xs);
  color: transparent;
}
.jr-tag-item[aria-selected="true"] .jr-tag-box {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-ink);
}
.jr-tag-foot {
  display: flex;
  justify-content: space-between;
  gap: var(--s2);
  padding: var(--s2);
  border-top: 1px solid var(--border-soft);
}

@media (max-width: 640px) {
  .jr-search { flex-basis: 100%; max-width: none; }
  .jr-tag-pick { width: min(260px, 78vw); }
}

/* --- Dashboard de Marketing (4-sep-2026) ---------------------------------- */
.mktd-post { display: block; }
.mktd-camp + .mktd-camp { margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--border-soft); }
.mktd-camp .progress { margin-top: var(--s2); }

/* El reparto por canal y por persona. Es una tabla con la barra dentro y no una
   tarta: con seis canales, una tarta obliga a mirar la leyenda para leer cada
   trozo, y aquí lo que se compara es «cuál lleva más», no la proporción. */
.mktd-bar { display: grid; grid-template-columns: 110px 1fr 32px; align-items: center; gap: var(--s3); }
.mktd-bar-lb { font-size: var(--fs-xs); color: var(--ink-2); }
.mktd-bar-track { height: 8px; border-radius: var(--r-full); background: var(--surface-3); overflow: hidden; }
.mktd-bar-fill { display: block; height: 100%; border-radius: var(--r-full); background: var(--primary); }
.mktd-bar-n { font-size: var(--fs-xs); font-weight: 600; color: var(--ink); text-align: right; }

@media (max-width: 640px) {
  .mktd-bar { grid-template-columns: 84px 1fr 28px; gap: var(--s2); }
}

/* ==========================================================================
   Constructor de encuestas (0105 · 4-sep-2026)
   --------------------------------------------------------------------------
   Página propia, «tipo Google Form». Dos columnas: a la izquierda lo que se
   arma, a la derecha de dónde se sacan las piezas. En móvil el panel baja
   debajo, porque con 375 px una columna de 260 px deja la otra inservible.
   ========================================================================== */

.svy-b-top { display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s4); }

/* El chip de guardado. Verde cuando no hay nada pendiente, ámbar cuando sí:
   es lo que evita cerrar la pestaña creyendo que quedó guardado. */
.svy-b-saved {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px var(--s3);
  border-radius: var(--r-full);
  font-size: var(--fs-xs); font-weight: 500;
  background: var(--success-soft); color: var(--success);
}
.svy-b-saved.is-dirty { background: var(--warning-soft, rgba(234,88,12,.12)); color: var(--warning); }

.svy-b-grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: var(--s5); align-items: start; }
.svy-b-side { position: sticky; top: var(--s4); }
.svy-b-side-t { font-size: var(--fs-xs); font-weight: 700; color: var(--ink); margin-bottom: var(--s2); }
.svy-b-side-s { margin: 0 0 var(--s2); font-size: var(--fs-xs); color: var(--ink-4); }

/* Un tipo de pregunta o una plantilla, en el panel de la derecha. */
.svy-b-pick {
  display: flex; align-items: center; gap: var(--s3);
  width: 100%; padding: var(--s2) var(--s3);
  border: 1px solid var(--border-soft); border-radius: var(--r-md);
  background: var(--surface); text-align: left; cursor: pointer;
  margin-bottom: 6px;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.svy-b-pick:hover { border-color: var(--primary); background: var(--primary-soft); }
.svy-b-pick-t { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--ink); }
.svy-b-pick-s { display: block; font-size: var(--fs-xs); color: var(--ink-4); }
.svy-b-pick-go { color: var(--ink-4); flex: none; }

/* El cuadradito de color del tipo. Cada tipo el suyo: es lo que permite
   reconocer una pregunta en la lista sin leer su etiqueta. */
.svy-qt-ico {
  flex: none; width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: var(--r-sm);
  background: var(--primary-soft); color: var(--primary);
}
.svy-qt-ico[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.svy-qt-ico[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.svy-qt-ico[data-tone="warning"] { background: var(--warning-soft, rgba(234,88,12,.12)); color: var(--warning); }
.svy-qt-ico[data-tone="info"]    { background: var(--info-soft, var(--primary-soft)); color: var(--info, var(--primary)); }
.svy-qt-ico[data-tone="purple"]  { background: var(--purple-soft, var(--primary-soft)); color: var(--purple, var(--primary)); }

/* --- Una pregunta de la lista ------------------------------------------- */
.svy-b-q {
  border: 1px solid var(--border-soft); border-radius: var(--r-md);
  background: var(--surface); margin-bottom: var(--s2);
}
.svy-b-q.is-open { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.svy-b-q.is-dragging { opacity: .4; }
.svy-b-q.is-over { border-color: var(--primary); }
.svy-b-q-head { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3); }
.svy-b-grip { color: var(--ink-4); cursor: grab; flex: none; }
.svy-b-num {
  flex: none; width: 24px; height: 24px;
  display: grid; place-items: center;
  border-radius: var(--r-full);
  background: var(--surface-3); color: var(--ink-3);
  font-size: var(--fs-xs); font-weight: 600;
}
.svy-b-t { font-size: var(--fs-sm); font-weight: 500; color: var(--ink); }
.svy-b-s { font-size: var(--fs-xs); color: var(--ink-4); }
.svy-b-del:hover { color: var(--danger); }
.svy-b-q.is-open .svy-b-chev { transform: rotate(180deg); }
.svy-b-q-body {
  display: flex; flex-direction: column; gap: var(--s3);
  padding: var(--s3); border-top: 1px solid var(--border-soft);
}
.svy-b-opts { display: flex; flex-direction: column; gap: var(--s2); }
.svy-b-op { display: flex; align-items: center; gap: var(--s2); }
.svy-b-op-ico { color: var(--ink-4); flex: none; }
.svy-b-op-pad { width: 28px; flex: none; }
.svy-b-req { align-self: flex-start; }
.svy-b-errs { margin: 0; padding-left: var(--s5); font-size: var(--fs-sm); color: var(--ink-2); }
.svy-b-errs li + li { margin-top: 6px; }
.svy-b-foot { display: flex; justify-content: flex-end; margin-top: var(--s5); }

@media (max-width: 1000px) {
  .svy-b-grid { grid-template-columns: minmax(0, 1fr); }
  .svy-b-side { position: static; }
}
@media (max-width: 640px) {
  .svy-b-top { flex-wrap: wrap; }
  .svy-b-meta { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ==========================================================================
   Inicio · los bloques del boceto (4-sep-2026)
   --------------------------------------------------------------------------
   Antes eran tarjetas de «un número y un enlace». El boceto de Juan pide
   listas: lo que hay, no cuánto hay. Un panel personal se mira treinta
   segundos, y en treinta segundos se lee una lista.
   ========================================================================== */

/* Las tres de arriba se estiran a la misma altura aunque una traiga cuatro
   filas y otra ninguna: si no, la fila queda con escalones. */
/* Las tres de arriba a la MISMA altura, y con el cuerpo estirado para que sus
   pies queden a la misma linea aunque una traiga cinco filas y otra ninguna.
   Sin esto la fila queda con escalones y se lee como si algo faltara. */
.home-row { align-items: stretch; }
.home-row > .home-card { display: flex; flex-direction: column; height: 100%; }
.home-card > .card-body { flex: 1 1 auto; display: flex; flex-direction: column; }
/* Lo que vaya al final del cuerpo --la nota del saldo, el aviso de vencidas--
   se pega abajo en vez de quedarse flotando a media tarjeta. */
.home-card > .card-body > .home-note { margin-top: auto; }
.home-card > .card-body > .home-list { flex: 0 0 auto; }
.home-card-foot {
  display: flex; justify-content: flex-end;
  padding: var(--s2) var(--s4) var(--s3);
  border-top: 1px solid var(--border-soft);
}

/* Abajo: avisos estrecho, calendario ancho. Es la proporción del boceto, y no
   es capricho — un aviso es una línea corta y un evento lleva título, país y
   fecha. */
/* `stretch` y no `start`. Juan pidio que las dos tarjetas midan lo mismo, y
   bajar el calendario a seis filas no bastaba: un aviso ocupa dos lineas
   --titulo y detalle-- y un evento una, asi que a igual numero de filas la de
   eventos seguia terminando mas arriba. Con las dos estiradas a la altura de
   la fila, cierran juntas pase lo que pase con el contenido. */
.home-row2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.9fr); gap: var(--s5); align-items: stretch; }
/* En columna, como las de arriba: el cuerpo crece y el pie cierra la tarjeta.
   Con el cuerpo a `height: 100%` el pie quedaba FUERA, debajo de la tarjeta,
   y alargaba la página (23-sep-2026). */
.home-row2 > .card { height: 100%; display: flex; flex-direction: column; }

.home-big {
  font-family: var(--font-display);
  font-size: clamp(20px, 2.4vw, 26px); font-weight: 600;
  letter-spacing: -.01em; color: var(--ink);
}
.home-big-sep { color: var(--ink-4); margin: 0 6px; font-weight: 400; }

/* --- Una fila de lista --------------------------------------------------- */
.home-list { display: flex; flex-direction: column; }
.hm-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) 0;
  color: inherit;
}
.hm-row + .hm-row { border-top: 1px solid var(--border-soft); }

/* --- Aviso con su boton de «Leido» -------------------------------------- */
/* El contenido enlaza a donde pasa la cosa; el boton la retira. Son dos
   objetivos distintos en la misma fila, y por eso el boton vive FUERA del
   enlace: dentro seria HTML invalido y el clic acabaria navegando. */
.hm-row-av { gap: var(--s2); }
.hm-row-av .hm-link {
  display: flex; align-items: center; gap: var(--s3);
  flex: 1 1 auto; min-width: 0; color: inherit; text-decoration: none;
}
a.hm-link:hover .hm-t { color: var(--primary); }
.hm-read {
  flex: none; display: inline-flex; align-items: center; gap: 4px;
  height: 26px; padding: 0 var(--s2);
  border: 1px solid var(--border); border-radius: 999px;
  background: transparent; color: var(--ink-3);
  font-size: var(--fs-2xs); font-weight: 600; cursor: pointer;
  /* Se ve siempre y no solo al pasar por encima: en tactil no hay «encima», y
     esta es la unica forma de quitarse un aviso desde el telefono. */
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.hm-read:hover { background: var(--success-soft); color: var(--success); border-color: transparent; }
.hm-read:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.hm-read svg { width: 13px; height: 13px; }

/* --- Leyenda del reparto por tienda ------------------------------------- */
/* La cabecera de la grafica lleva su propio selector a la derecha. `wrap`
   porque en «Personalizado» son tres campos y no caben junto al titulo. */
.mgt-chart-head { display: flex; align-items: flex-start; gap: var(--s3); flex-wrap: wrap; }
.mgt-chart-head .fsel { flex: none; }

.mgt-leg { display: flex; align-items: center; gap: var(--s3); }
.mgt-leg-dot { flex: none; width: 10px; height: 10px; border-radius: 999px; }

/* --- B2C · una tarjeta por linea de venta, con su meta ------------------- */
/* Las dos secciones llevan el MISMO orden --meta arriba, cifras debajo, top al
   final-- para que se lean en paralelo sin aprender dos formatos. */
.mgt-linea-ico {
  display: inline-grid; place-items: center; flex: none;
  width: 38px; height: 38px; border-radius: var(--r-md);
}
.mgt-linea-ico svg { width: 19px; height: 19px; }

.mgt-meta { padding: var(--s4); border-radius: var(--r-md); background: var(--surface-2); }
.mgt-meta-bar { display: flex; align-items: center; gap: var(--s3); }
/* `min-width: 0` ademas del `flex`: `.progress` trae `width: 100%` y sin esto
   se lleva la fila entera y empuja el porcentaje al renglon de abajo. */
.mgt-meta-bar .progress { flex: 1 1 auto; min-width: 0; width: auto; }
.mgt-meta-pct {
  flex: none; min-width: 52px; text-align: right;
  font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 600;
  letter-spacing: -.02em;
}

/* Cuatro cifras en fila, y a la mitad de ancho dos y dos: nunca una sola
   columna, que estira la tarjeta y rompe la lectura en paralelo. */
.mgt-minis { display: grid; gap: var(--s3); grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 900px) { .mgt-minis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.mgt-mini {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--s3); border-radius: var(--r-md); background: var(--surface-2);
}
.mgt-mini-lb { font-size: var(--fs-2xs); font-weight: 600; color: var(--ink-3); }
.mgt-mini-vl {
  font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 600;
  letter-spacing: -.02em;
}

/* Una fila del editor de metas: el mes a la izquierda, su casilla a la derecha. */
.mgt-meta-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: var(--s2) 0;
}
.mgt-meta-row + .mgt-meta-row { border-top: 1px solid var(--border-soft); }
.mgt-meta-row input { width: 130px; text-align: right; }

/* --- Extracto del registro en el panel ---------------------------------- */
.mgt-act { display: flex; align-items: center; gap: var(--s3); }
.mgt-act-ico {
  flex: none; display: inline-grid; place-items: center;
  width: 26px; height: 26px; border-radius: var(--r-sm, var(--r-md));
  background: var(--neutral-soft); color: var(--ink-2);
}
.mgt-act-ico[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.mgt-act-ico[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.mgt-act-ico[data-tone="primary"] { background: var(--primary-soft); color: var(--primary); }
.mgt-act-ico svg { width: 13px; height: 13px; }

a.hm-row:hover .hm-t { color: var(--primary); }
.hm-ico {
  flex: none; width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: var(--r-sm);
  background: var(--primary-soft); color: var(--primary);
}
.hm-ico[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.hm-ico[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.hm-ico[data-tone="warning"] { background: var(--warning-soft); color: var(--warning); }
.hm-ico[data-tone="info"]    { background: var(--info-soft, var(--primary-soft)); color: var(--info, var(--primary)); }
.hm-ico[data-tone="accent"]  { background: var(--accent-soft, var(--primary-soft)); color: var(--accent, var(--primary)); }
.hm-ico[data-tone="purple"]  { background: var(--purple-soft, var(--primary-soft)); color: var(--purple, var(--primary)); }
.hm-ico[data-tone="magenta"] { background: var(--magenta-soft, var(--primary-soft)); color: var(--magenta, var(--primary)); }
.hm-ico[data-tone="muted"]   { background: var(--surface-3); color: var(--ink-3); }
.hm-t { display: block; font-size: var(--fs-sm); font-weight: 500; color: var(--ink); }
.hm-s { display: block; font-size: var(--fs-xs); color: var(--ink-4); }
.hm-key { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink-4); }

/* El punto de «sin leer». Un punto y no un badge: hay uno por fila y un badge
   por fila convierte la lista en una pared de color. */
.hm-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--primary); }

.hm-due, .hm-when {
  display: inline-flex; align-items: center; gap: 4px;
  flex: none; white-space: nowrap;
  font-size: var(--fs-xs); color: var(--ink-4);
}
.hm-due[data-tone="danger"]  { color: var(--danger); font-weight: 600; }
.hm-due[data-tone="warning"] { color: var(--warning); font-weight: 600; }
.hm-when { gap: var(--s2); }
.hm-pais {
  padding: 1px 6px; border-radius: var(--r-full);
  background: var(--surface-3); color: var(--ink-3);
  font-size: var(--fs-2xs, 10px);
}

/* La nota del pie de un bloque: el dato que dejó de ser el titular. */
.home-note {
  display: flex; align-items: center; gap: 6px;
  margin-top: var(--s3); padding-top: var(--s3);
  border-top: 1px solid var(--border-soft);
  font-size: var(--fs-xs); color: var(--ink-4);
}
.home-note.is-danger { color: var(--danger); }

@media (max-width: 900px) {
  .home-row2 { grid-template-columns: minmax(0, 1fr); }
}

/* --- Ficha de la persona · su JIRA, en solo lectura (4-sep-2026) ---------- */
.pf-jira-note {
  display: flex; align-items: center; gap: 6px;
  margin: 0; font-size: var(--fs-xs); color: var(--ink-4);
}
/* Sin `cursor: grab` y sin sombra al pasar: la tarjeta no se mueve, y darle
   pinta de arrastrable es invitar a un gesto que no va a funcionar. */
.pf-jira .kb-cards { min-height: 60px; }
.pf-jira-card { cursor: default; }
.pf-jira-card:hover { box-shadow: none; transform: none; }
.pf-jira-card.is-late { border-left: 3px solid var(--danger); }
.t-clip-2 {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* --- Ficha · el rango de los indicadores (4-sep-2026) --------------------- */
/* Van pequeños porque viven en la cabecera de una tarjeta, al lado del título:
   a tamaño normal el selector pesa más que el rótulo que acompaña. */
.kpi-range .select-sm, .kpi-range .input-sm {
  height: 30px; padding: 0 var(--s2); font-size: var(--fs-xs); width: auto;
}
.kpi-range .input-sm { min-width: 128px; }
@media (max-width: 640px) {
  .kpi-range { flex-wrap: wrap; justify-content: flex-end; }
}

/* La bandera dibujada del bloque de calendario. Windows no trae glifos de
   bandera —pinta las dos letras del ISO—, así que van en SVG (`UI.flagOf`). */
.flag-svg {
  width: 15px; height: 11px;
  border-radius: 2px;
  flex: none;
  box-shadow: 0 0 0 1px rgba(20, 26, 51, .12) inset;
}
.hm-pais { display: inline-flex; align-items: center; gap: 5px; }

/* ==========================================================================
   JIRA · Transfers entre equipos (0107 · 5-sep-2026)
   --------------------------------------------------------------------------
   La bandeja de lo que otro equipo le pasó a este. Tarjetas anchas y no un
   tablero: aquí no se arrastra nada, se lee y se decide.
   ========================================================================== */

.tr-list { display: flex; flex-direction: column; gap: var(--s3); }
.tr-card {
  border: 1px solid var(--border-soft); border-radius: var(--r-lg);
  background: var(--surface); padding: var(--s4);
}
.tr-card-top { display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s2); }
/* De dónde viene y a dónde va, con la flecha en medio: es lo primero que hay
   que entender de una tarjeta que aparece en una bandeja ajena. */
.tr-flow {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-xs); color: var(--ink-4);
}
.tr-title { margin: 0 0 var(--s2); font-size: var(--fs-md); font-weight: 600; }
.tr-title a { color: var(--ink); }
.tr-title a:hover { color: var(--primary); }
.tr-meta {
  display: flex; flex-wrap: wrap; gap: var(--s4);
  font-size: var(--fs-xs); color: var(--ink-4);
}
.tr-meta > span { display: inline-flex; align-items: center; gap: 5px; }
.tr-note {
  display: flex; align-items: flex-start; gap: 6px;
  margin: var(--s3) 0 0; padding: var(--s2) var(--s3);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font-size: var(--fs-xs); color: var(--ink-2);
}
/* El motivo del rechazo se distingue de la nota de envío: son dos voces
   distintas y en una devuelta se buscan las dos. */
.tr-note.is-deny { background: var(--danger-soft); color: var(--danger); }
.tr-actions { display: flex; justify-content: flex-end; gap: var(--s2); margin-top: var(--s3); }
.tr-onlylead {
  display: flex; align-items: center; gap: 5px;
  margin: var(--s3) 0 0; font-size: var(--fs-xs); color: var(--ink-4);
}
/* El contador de la pestaña. Con cero no se pinta —una pestaña que siempre
   lleva un 0 al lado enseña a no mirar el número. */
.tab-n {
  margin-left: 6px; padding: 0 6px;
  border-radius: var(--r-full);
  background: var(--primary-soft); color: var(--primary);
  font-size: var(--fs-2xs); font-weight: 700;
}
@media (max-width: 640px) {
  .tr-meta { gap: var(--s2) var(--s3); }
  .tr-actions { flex-direction: column-reverse; }
  .tr-actions .btn { width: 100%; justify-content: center; }
}

/* ==========================================================================
   Inicio · el cielo de la franja, y las columnas agrupadas (5-sep-2026)
   ========================================================================== */

/* --- El cielo ------------------------------------------------------------
   El color va por tramo del día; la POSICIÓN del sol la calcula el JS y llega
   en `--x`/`--y`. Aquí solo se pinta y se mueve. */
.sky .sky-hill   { fill: #0a1034; opacity: .55; }
.sky .sky-hill-2 { fill: #0a1034; opacity: .3; }
.sky .sky-cloud  { fill: #fff; opacity: .3; }
.sky .sky-moon-cut { fill: #101a3d; }

.sky[data-sky="manana"] .sky-cloud { opacity: .38; }
.sky[data-sky="tarde"]  .sky-cloud { opacity: .45; }
/* Al atardecer las nubes se tiñen: es lo que hace que se lea «atardece» sin
   necesidad de mover el sol más abajo de lo que ya está. */
.sky[data-sky="ocaso"]  .sky-cloud { fill: #ffb37a; opacity: .4; }
.sky[data-sky="ocaso"]  .sky-sun circle { fill: #ff8a4d; }
.sky[data-sky="ocaso"]  .sky-halo { fill: #ff8a4d; }
.sky[data-sky="noche"]  .sky-cloud { opacity: .12; }

/* El astro se coloca con `transform` y no con cx/cy: así la animación del halo
   no pelea con la posición, y el navegador la resuelve sin recalcular nada. */
.sky-sun, .sky-moon { transform: translate(var(--x), var(--y)); }
.sky-cloud { transform: translate(var(--x), var(--y)) scale(var(--k)); }

/* El halo respira. Dos capas con distinto retardo: una sola pulsando se lee
   como un parpadeo, dos desfasadas se leen como luz. */
@keyframes sky-breathe {
  0%, 100% { transform: scale(1);    opacity: .18; }
  50%      { transform: scale(1.14); opacity: .28; }
}
.sky-halo { animation: sky-breathe 4.5s ease-in-out infinite; transform-origin: center; }
.sky-halo-2 { animation-duration: 6s; animation-delay: -1.5s; }

/* Las nubes cruzan, muy despacio: es fondo, no un carrusel. */
@keyframes sky-drift {
  from { transform: translate(var(--x), var(--y)) scale(var(--k)); }
  to   { transform: translate(calc(var(--x) + 26px), var(--y)) scale(var(--k)); }
}
.sky-cloud.c1 { animation: sky-drift 26s ease-in-out infinite alternate; }
.sky-cloud.c2 { animation: sky-drift 34s ease-in-out infinite alternate; animation-delay: -8s; }

@keyframes sky-twinkle { 0%, 100% { opacity: .25 } 50% { opacity: .9 } }
.sky-star { animation: sky-twinkle 3.2s ease-in-out infinite; animation-delay: calc(var(--i) * .4s); }

/* Quien pidió menos movimiento no lo tiene: el cielo sigue diciendo la hora
   por su color y la posición del astro, que es lo que informa. */
@media (prefers-reduced-motion: reduce) {
  .sky-halo, .sky-cloud, .sky-star { animation: none; }
}

/* --- Columnas agrupadas: dos barras por día ------------------------------
   Las del mismo día van pegadas y los días separados: lo que se compara es
   dentro del día, no un día contra otro. */
.cg-chart .cc-bars { align-items: flex-end; gap: var(--s4); }
.cg-group { display: flex; align-items: flex-end; gap: 3px; height: 100%; flex: 1 1 0; }
.cg-bar {
  flex: 1 1 0; max-width: 22px;
  background: var(--cc-c);
  border-radius: 4px 4px 0 0;
  min-height: 2px;
  animation: cc-rise .5s var(--ease) both;
  animation-delay: calc(var(--i, 0) * .06s);
}
.cg-bar.is-zero { background: var(--surface-3); }
@keyframes cc-rise { from { transform: scaleY(0) } to { transform: scaleY(1) } }
.cg-bar { transform-origin: bottom; }
@media (prefers-reduced-motion: reduce) { .cg-bar { animation: none; } }

/* ==========================================================================
   Registro de auditoría (0108 · 5-sep-2026)
   --------------------------------------------------------------------------
   Una línea por cambio, en rejilla de columnas fijas: cuándo, quién, qué y qué
   campos. Las columnas alineadas son lo que permite recorrer cincuenta líneas
   con la vista sin leerlas una por una — que es como se usa un log.
   ========================================================================== */

.aud-filters { flex-wrap: wrap; align-items: center; gap: var(--s2); }
.aud-filters .select-sm, .aud-filters .input-sm {
  height: 34px; font-size: var(--fs-xs); width: auto;
  /* EL RELLENO NO SE ESCRIBE EN ATAJO, Y ESA ERA LA AVERIA.
     `padding: 0 var(--s2)` ponia 8 px a los CUATRO lados y con eso borraba los
     34 px que `.select` y `.input[type=date]` reservan a la derecha para su
     icono. El texto se metia debajo: el «dd/mm/aaaa» pisando el calendario y
     el nombre del filtro pisando la flecha. Se toca solo el lado izquierdo y
     se deja sitio al icono en el derecho. */
  padding-left: var(--s2);
  padding-right: 28px;
  background-position: right 8px center;
}
/* `.select` fija `line-height: 38px` para centrar su texto en un control de 40;
   con 34 de alto hay que bajarla o el texto se va arriba. */
.aud-filters .select-sm { line-height: 32px; }
/* Sin minimo, el campo se encogia a lo que el navegador quisiera --se midieron
   18 px-- y no cabia ni la fecha ni el icono. */
.aud-filters .input-sm[type="date"] { min-width: 136px; }
.aud-list { border: 1px solid var(--border-soft); border-radius: var(--r-md); overflow: hidden; }
.aud-row + .aud-row { border-top: 1px solid var(--border-soft); }

.aud-head {
  display: grid;
  grid-template-columns: 28px 132px 140px minmax(0, 1.4fr) minmax(0, 1fr) 20px;
  align-items: center; gap: var(--s3);
  width: 100%; padding: var(--s2) var(--s3);
  background: var(--surface); border: 0; text-align: left; cursor: pointer;
  font-size: var(--fs-xs); color: var(--ink-2);
}
.aud-head:hover { background: var(--surface-2); }
.aud-ico {
  width: 24px; height: 24px; display: grid; place-items: center;
  border-radius: var(--r-sm); background: var(--primary-soft); color: var(--primary);
}
.aud-ico[data-tone="success"] { background: var(--success-soft); color: var(--success); }
.aud-ico[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.aud-when { color: var(--ink-4); }
.aud-who  { font-weight: 600; color: var(--ink); }
.aud-fields { color: var(--ink-4); font-family: var(--font-mono); font-size: var(--fs-2xs); }
.aud-chev { color: var(--ink-4); transition: transform var(--t-fast) var(--ease); }
.aud-head[aria-expanded="true"] .aud-chev { transform: rotate(180deg); }
.aud-body { padding: 0 var(--s3) var(--s3); background: var(--surface-2); }
.aud-diff td { font-size: var(--fs-xs); vertical-align: top; }
.aud-diff td:first-child { font-family: var(--font-mono); color: var(--ink-4); white-space: nowrap; }
.aud-masked {
  display: flex; align-items: center; gap: 6px;
  margin: 0; padding: var(--s3) 0;
  font-size: var(--fs-xs); color: var(--ink-4);
}
.chip-x {
  display: inline-grid; place-items: center;
  margin-left: 4px; padding: 0; width: 16px; height: 16px;
  border: 0; border-radius: 50%; background: transparent;
  color: inherit; cursor: pointer;
}
.chip-x:hover { background: var(--primary-soft); }

/* A partir de tableta la rejilla no cabe: cada línea pasa a apilarse, y la
   fecha deja de tener ancho fijo. */
@media (max-width: 900px) {
  .aud-head {
    grid-template-columns: 28px minmax(0, 1fr) 20px;
    grid-template-areas: 'ico what chev' 'ico who chev' 'ico when chev' 'ico fields chev';
    row-gap: 2px;
  }
  .aud-ico { grid-area: ico; align-self: start; }
  .aud-what { grid-area: what; }
  .aud-who { grid-area: who; }
  /* La hora se queda: un registro sin «cuando» no responde nada. Lo que cambia
     es que deja de tener columna propia y baja a su linea. */
  .aud-when { grid-area: when; }
  .aud-fields { grid-area: fields; }
}

/* ============================================ Salud de la plataforma (0109) */

/* La franja de arriba: cuatro números que se leen sin bajar. Va también sobre
   el registro de auditoría, porque Juan pidió verlos «en esa página». */
.sal-strip {
  display: grid; gap: var(--s4);
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.sal-tile { padding: var(--s4); display: flex; flex-direction: column; gap: 2px; }
.sal-tile .stat-value { font-size: var(--fs-2xl); line-height: 1.1; }
.sal-tile .stat-foot { font-size: var(--fs-xs); color: var(--ink-4); }

/* Dos columnas en escritorio. La primera tarjeta —la tendencia— ocupa el ancho
   entero: es la única que responde «hacia dónde va» y encogerla la vuelve
   ilegible justo en la pregunta que importa. */
.sal-grid { display: grid; gap: var(--s4); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sal-grid > .card:first-child { grid-column: 1 / -1; }

/* Una tabla grande: nombre, barra proporcional a la mayor, y su tamaño. */
.sal-row {
  display: grid; align-items: center; gap: var(--s3);
  grid-template-columns: minmax(0, 1.4fr) minmax(60px, 1fr) auto auto;
  padding: 5px 0;
  border-top: 1px solid var(--border-soft, var(--border));
}
.sal-row:first-of-type { border-top: 0; }
.sal-row-name {
  font-family: var(--font-mono); font-size: var(--fs-xs);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sal-row-val { font-size: var(--fs-xs); font-weight: 600; text-align: right; }
.sal-row-sub { font-size: var(--fs-2xs); color: var(--ink-4); text-align: right; white-space: nowrap; }

/* El texto de una consulta. Se corta con puntos suspensivos en vez de romper la
   tabla: aquí interesa reconocerla, no leerla entera. */
.sal-q {
  display: inline-block; max-width: 100%;
  font-family: var(--font-mono); font-size: var(--fs-2xs);
  color: var(--ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  vertical-align: bottom;
}

.sal-job {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) 0;
  border-top: 1px solid var(--border-soft, var(--border));
}
.sal-job:first-child { border-top: 0; }

/* El punto de estado nunca va solo: al lado siempre hay texto que dice lo
   mismo, porque el color no es identidad. */
.sal-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--ink-4); }
.sal-dot[data-tone="success"] { background: var(--success); }
.sal-dot[data-tone="danger"]  { background: var(--danger); }
.sal-dot[data-tone="muted"]   { background: var(--ink-4); }

@media (max-width: 1100px) {
  .sal-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 900px) {
  .sal-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sal-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: 'name val' 'bar sub';
  }
  .sal-row-name { grid-area: name; }
  .sal-row-val { grid-area: val; }
  .sal-row .progress { grid-area: bar; }
  .sal-row-sub { grid-area: sub; }
}

/* La tabla de consultas vive en media rejilla, así que las columnas se reparten
   a lo fijo: sin esto el texto de una consulta —que va en una sola línea— estira
   la tabla y empuja los números fuera de la tarjeta. */
.sal-view .table { table-layout: fixed; }
.sal-view .table th:first-child, .sal-view .table td:first-child { width: 44%; }
.sal-view .table th:not(:first-child), .sal-view .table td:not(:first-child) { width: 14%; }

/* Un horario de cron son espacios significativos, y HTML los colapsa: lo que
   se escribe con cinco campos separados acaba leyendose pegado, y pegado ya no
   es el horario. (Y ojo con citarlo en un comentario CSS: la barra despues del
   asterisco lo CIERRA antes de tiempo y se lleva la regla de abajo. Paso.) */
.sal-cron { white-space: pre; font-family: var(--font-mono); }
.sal-mal { color: var(--danger); font-weight: 600; }

/* ==========================================================================
   PRESUPUESTO (0113)
   Una barra de tres tramos y dos tablas. Los colores dicen tres cosas
   distintas —lo que salió, lo que está contratado y lo que espera decisión—
   y por eso no es una barra de progreso: una sola magnitud no puede
   responder «¿cuánto me queda de verdad?».
   ========================================================================== */

.bud-month { display: inline-flex; align-items: center; gap: var(--s1); }
.bud-month-label {
  min-width: 132px; text-align: center;
  font-size: var(--fs-md); font-weight: 600; text-transform: capitalize;
}
/* El mes en curso es el tope: adelante no hay nada que mirar, y un botón que
   no lleva a ninguna parte se apaga en vez de desaparecer —si desapareciera,
   la flecha de atrás saltaría de sitio al cambiar de mes—. */
.bud-month .is-off { opacity: .35; pointer-events: none; }

.bud-bar {
  display: flex; width: 100%; height: 16px; overflow: hidden;
  background: var(--surface-3); border-radius: var(--r-full);
}
.bud-bar-sm { height: 8px; min-width: 96px; }
.bud-seg { display: block; height: 100%; }
.bud-seg[data-k="gastado"]   { background: var(--c1); }
.bud-seg[data-k="saas"]      { background: var(--c4); }
/* Lo pendiente va rayado: no es plata que salió, es plata que alguien pidió.
   Pintarlo plano lo haría indistinguible de lo gastado a un metro de la
   pantalla, que es la distancia a la que se mira un panel. */
.bud-seg[data-k="pendiente"] {
  background: repeating-linear-gradient(45deg,
    var(--warning) 0 5px, transparent 5px 10px), var(--surface-3);
}
.bud-bar.is-over { box-shadow: inset 0 0 0 1.5px var(--danger); }
.bud-bar.is-empty { align-items: center; justify-content: center; height: auto; padding: var(--s2); }
.bud-bar-none { font-size: var(--fs-sm); color: var(--ink-4); }

.bud-legend { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); margin-top: var(--s3); }
.bud-dot { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.bud-dot[data-k="gastado"]   { background: var(--c1); }
.bud-dot[data-k="saas"]      { background: var(--c4); }
.bud-dot[data-k="pendiente"] { background: var(--warning); }

/* Mismo reparto que el panel de Tecnología: el libro manda y el software
   acompaña. Debajo de 1100 px se apilan, con el libro primero. */
.bud-split { display: grid; gap: var(--s5); grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); }
@media (max-width: 1100px) { .bud-split { grid-template-columns: minmax(0, 1fr); } }

.bud-table { min-width: 480px; }
.bud-table th, .bud-table td { padding-left: var(--s2); padding-right: var(--s2); }
.bud-areas { min-width: 720px; }
.bud-cell-bar { width: 120px; }

/* El cuadradito del icono de categoría: el mismo lenguaje que el tipo de tarea
   en JIRA, para que una fila de gasto se lea igual que una de trabajo. */
.bud-cat {
  display: inline-grid; place-items: center; flex: none;
  width: 22px; height: 22px; border-radius: var(--r-sm);
  background: var(--surface-3); color: var(--ink-3);
}

.bud-area-link { font-weight: 600; color: var(--ink-1); }
.bud-area-link:hover { color: var(--primary); }

/* El límite se edita desde la propia fila. Es un botón y parece texto: lo que
   se lee es la cifra, y el lápiz solo aparece al pasar por encima. */
.bud-limit {
  display: inline-flex; align-items: center; gap: var(--s1);
  font: inherit; color: inherit; cursor: pointer;
  background: none; border: 0; padding: 2px 4px; border-radius: var(--r-sm);
}
.bud-limit svg { opacity: 0; color: var(--ink-4); }
.bud-limit:hover { background: var(--surface-3); }
.bud-limit:hover svg, .bud-limit:focus-visible svg { opacity: 1; }

.bud-saas-list { display: flex; flex-direction: column; gap: 2px; }
.bud-saas {
  display: flex; align-items: center; gap: var(--s3); width: 100%;
  padding: var(--s2) var(--s2); text-align: left; cursor: pointer;
  background: none; border: 0; border-radius: var(--r-md); color: inherit;
}
.bud-saas:hover { background: var(--surface-3); }
.bud-saas .grow { display: flex; flex-direction: column; gap: 1px; }
.bud-saas-foot {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: var(--s2); padding-top: var(--s2); border-top: 1px solid var(--border);
}

/* ==========================================================================
   Upselling Auto · antes «CRM de Renovaciones» (0117, 0125)
   ========================================================================== */

.crm-bar { margin-bottom: var(--s4); }
/* Los `.select` de la casa nacen a `width:100%`, que en una fila flexible
   empuja cada uno a su propio renglon: el buscador arriba y los dos filtros
   debajo, ocupando tres lineas para tres controles. Se les devuelve su ancho
   aqui y solo aqui. */
.crm-bar .row > .select { width: auto; min-width: 12rem; flex: 0 0 auto; }
.crm-bar .row > .input { width: auto; min-width: 16rem; flex: 1 1 16rem; }

.crm-tabs {
  display: flex; flex-wrap: wrap; gap: var(--s1);
  margin-top: var(--s3); padding-top: var(--s3);
  border-top: 1px solid var(--border);
}
.crm-tab {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s3); border-radius: var(--r-md);
  font-size: var(--fs-sm); font-weight: 600;
  color: var(--ink-2); text-decoration: none;
  border: 1px solid transparent;
}
.crm-tab:hover { background: var(--surface-3); color: var(--ink); }
.crm-tab.is-on {
  background: var(--primary); color: var(--primary-ink); border-color: var(--primary);
}
.crm-tab-n {
  font-size: var(--fs-2xs); font-weight: 700;
  padding: 1px var(--s2); border-radius: var(--r-full);
  background: var(--surface-3); color: var(--ink-3);
}
.crm-tab.is-on .crm-tab-n { background: rgba(255, 255, 255, .22); color: inherit; }

/* El responsable, cambiable desde la fila (0119). No parece un campo de
   formulario hasta que se le pasa el ratón: en una tabla de 24 filas, 24
   cajas con borde pesan más que los datos que acompañan. La altura baja a la
   de una fila de tabla y la línea baja con ella, por lo mismo que explica
   `.select` en components.css: con `appearance: none` el texto se centra con
   `line-height`, no solo.

   Sin ancho mínimo, y es medido: la tabla ya desbordaba a 1280 px antes de
   esta columna (1.048 px de tabla en 940 de tarjeta) y con `min-width: 9rem`
   pasaba a desbordar también a 1440. Al ancho de su contenido cabe a 1440
   (11-sep-2026). El margen negativo deja el texto a plomo con el título
   «Responsable»; el relleno izquierdo queda para el borde del hover.

   Y en UNA línea: al ancho de su contenido la tabla lo encogía, y «Gabriela
   Salazar» salía partido en dos renglones dentro de un control de 30 px. El
   nombre que no quepa se corta con puntos suspensivos; si la pantalla no da,
   la tabla se desplaza de lado, como ya hacía a 1280. */
.crm-owner.select {
  width: auto; max-width: 11rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  height: 30px; line-height: 28px;
  margin-left: calc(-1 * var(--s2));
  padding: 0 24px 0 var(--s2);
  font-size: var(--fs-sm);
  border-color: transparent; background-color: transparent;
  background-position: right 4px center;
}
.crm-owner.select:hover { border-color: var(--border-strong); background-color: var(--surface); }
.crm-owner.select:focus { border-color: var(--primary); background-color: var(--surface); }
.crm-owner.is-none { color: var(--ink-3); }
.crm-owner.select:disabled { background-color: transparent; cursor: progress; }

/* El historial de un lead. Se lee de arriba abajo y lo más reciente va
   primero, que es el orden en que se pregunta «¿qué pasó con este?». */
.crm-log { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.crm-log li {
  padding: var(--s2) 0; border-bottom: 1px solid var(--border-soft);
  display: flex; flex-wrap: wrap; gap: var(--s2); align-items: baseline;
}
.crm-log li:last-child { border-bottom: 0; }

/* El teléfono (0125), con dígitos de ancho fijo: una columna de números se
   lee como columna y no como texto corrido, y el «+57» queda alineado. */
.crm-tel { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Los lotes que salieron hacia Dapta (0125). Un lote deshecho se queda en la
   lista —es historial— pero atenuado: lo que ya no cuenta no debe pesar lo
   mismo que lo que sí. Y sus tres botones, pequeños y en fila. */
.crm-lotes tr.is-undone td { color: var(--ink-4); }
.crm-lotes tr.is-undone .t-bold { text-decoration: line-through; }
.crm-lote-acc { display: flex; gap: var(--s2); align-items: center; }

/* En el teléfono las pestañas no se parten en renglones: se desplazan de lado.
   Los tres cortes de `mobile.css` (900 / 640 / 400) se respetan; este vive
   aquí porque es del componente y no del reparto general de la página. */
@media (max-width: 640px) {
  .crm-tabs { overflow-x: auto; flex-wrap: nowrap; }
  .crm-tab { white-space: nowrap; }
}

/* ==========================================================================
   Equipo B2B · Partners y Mis Partners (0135)
   Se apoya en lo de Clientes (`cu-*`: barra, tabla de una línea, ficha en
   página) para que se lea igual; aquí va solo lo propio de un partner.
   Sin animaciones al filtrar o cambiar de vista: se usan decenas de veces
   al día. Solo la respuesta al pulsar.
   ========================================================================== */
.pt-card { overflow: hidden; }
.pt-views {
  padding: 0 var(--s4);
  border-bottom: 1px solid var(--border);
}
.pt-views .tab { gap: 6px; white-space: nowrap; }
.pt-views .tab svg { width: 15px; height: 15px; }
.pt-views .tab,
.pt-kinds button { transition: transform 160ms cubic-bezier(.23, 1, .32, 1), color var(--t-fast) var(--ease); }
.pt-views .tab:active,
.pt-kinds button:active { transform: scale(.97); }

/* Las columnas que ceden, como en Clientes. */
.pt-table .pt-w-name { width: 27%; }
.pt-table .pt-w-pais { width: 13%; }
.pt-table .pt-w-mail { width: 22%; }
.pt-table tr[data-pt]:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.pt-table mark { background: var(--primary-soft); color: inherit; border-radius: 3px; padding: 0 1px; }
.pt-mailcell { display: flex; align-items: center; gap: 6px; min-width: 0; }
.pt-mailcell .cu-mail { min-width: 0; }
.pt-more {
  flex: none; padding: 1px 6px; border-radius: var(--r-full);
  background: var(--neutral-soft); color: var(--ink-3);
  font-size: var(--fs-2xs); font-weight: 600; font-variant-numeric: tabular-nums;
}
.pt-fecha { color: var(--ink-3); }

/* Los programas: etiquetas pequeñas, cada una con su tinte. No se parten. */
.pt-progs { display: inline-flex; flex-wrap: nowrap; gap: 4px; }
.pt-prog {
  display: inline-flex; align-items: center; height: 20px; padding: 0 7px;
  border-radius: var(--r-full); white-space: nowrap;
  background: var(--primary-soft); color: var(--primary);
  font-size: var(--fs-2xs); font-weight: 600;
}
.pt-prog[data-prog="test_center"] { background: var(--info-soft); color: var(--info); }
.pt-prog[data-prog="rep"]         { background: var(--accent-soft); color: var(--accent); }
.pt-prog[data-prog="badges"]      { background: var(--warning-soft); color: var(--warning); }
.pt-prog[data-prog="universidad"] { background: var(--success-soft); color: var(--success); }

/* La renovación: la fecha y, al lado, cuánto falta o cuánto pasó. */
.pt-ren-rel { white-space: nowrap; color: var(--ink-2); }
.pt-ren-rel[data-tone] { padding: 2px 8px; border-radius: var(--r-full); font-weight: 600; }
.pt-ren-rel[data-tone="danger"]  { background: var(--danger-soft);  color: var(--danger); }
.pt-ren-rel[data-tone="warning"] { background: var(--warning-soft); color: var(--warning); }
.pt-table tr.is-inactive .cu-nm { color: var(--ink-3); font-weight: 500; }

.pt-next { display: inline-flex; align-items: baseline; gap: var(--s2); max-width: 26ch; }
.pt-next-tx { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-3); }

/* ---- La ficha ---- */
.pt-avatar { background: var(--primary-soft); color: var(--primary); }
.pt-avatar[data-cat="diamond"]  { background: var(--accent-soft);  color: var(--accent); }
.pt-avatar[data-cat="platinum"] { background: var(--info-soft);    color: var(--info); }
.pt-avatar[data-cat="silver"],
.pt-avatar[data-cat="avalado"],
.pt-avatar[data-cat="none"]     { background: var(--neutral-soft); color: var(--ink-2); }
.pt-avatar[data-cat="activo"]   { background: var(--success-soft); color: var(--success); }
.pt-avatar[data-cat="medio"]    { background: var(--warning-soft); color: var(--warning); }
.cu-kpi-ico[data-tone="danger"] { background: var(--danger-soft); color: var(--danger); }
.pt-kpi-vl { min-width: 0; }
.pt-kpi-clip { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.alert.pt-missing { align-items: center; }
.alert.pt-missing > div { flex: 1 1 auto; min-width: 0; }
.alert.pt-missing p { margin: 2px 0 0; }

/* Registrar un seguimiento: tipo, qué pasó, y el próximo paso en la misma
   pasada, que es cuando se decide. */
.pt-composer {
  display: flex; flex-direction: column; gap: var(--s3);
  padding: var(--s4); margin-bottom: var(--s5);
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-lg);
}
.pt-kinds { align-self: flex-start; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.pt-kinds::-webkit-scrollbar { display: none; }
.pt-kinds button { white-space: nowrap; }
/* `background-color` y no `background`: el atajo reinicia el `repeat` y el
   icono de calendario de la casa se repetía en los campos de fecha. */
.pt-composer .textarea { background-color: var(--surface); }
.pt-composer-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s3); }
.pt-mini { display: flex; flex-direction: column; gap: 6px; min-width: 150px; }
.pt-mini > span { font-size: var(--fs-xs); font-weight: 500; color: var(--ink-3); }
.pt-mini .input { background-color: var(--surface); }
.pt-log-btn { height: 40px; }

.pt-timeline { list-style: none; margin: 0; padding: 0; position: relative; }
.pt-timeline::before {
  content: ''; position: absolute; left: 15px; top: 8px; bottom: 8px;
  width: 1px; background: var(--border);
}
.pt-ev { position: relative; display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: var(--s3); padding: 0 0 var(--s4); }
.pt-ev:last-child { padding-bottom: 0; }
.pt-ev-ico {
  position: relative; z-index: 1;
  display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--border); color: var(--ink-3);
}
.pt-ev[data-kind="llamada"] .pt-ev-ico    { background: var(--primary-soft); border-color: transparent; color: var(--primary); }
.pt-ev[data-kind="whatsapp"] .pt-ev-ico   { background: var(--success-soft); border-color: transparent; color: var(--success); }
.pt-ev[data-kind="correo"] .pt-ev-ico     { background: var(--info-soft);    border-color: transparent; color: var(--info); }
.pt-ev[data-kind="reunion"] .pt-ev-ico    { background: var(--accent-soft);  border-color: transparent; color: var(--accent); }
.pt-ev[data-kind="renovacion"] .pt-ev-ico { background: var(--warning-soft); border-color: transparent; color: var(--warning); }
.pt-ev-main { min-width: 0; padding-top: 5px; }
.pt-ev-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--s2); font-size: var(--fs-sm); }
.pt-ev-at { margin-left: auto; font-size: var(--fs-xs); color: var(--ink-4); white-space: nowrap; }
.pt-ev-body {
  margin-top: 4px; color: var(--ink-2); font-size: var(--fs-md);
  white-space: pre-line; overflow-wrap: anywhere;
}

.pt-list { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.pt-li { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.pt-li > a:first-child { overflow-wrap: anywhere; }
.pt-copy { width: 26px; height: 26px; }
.pt-wa {
  display: inline-flex; align-items: center; gap: 4px; padding: 1px 8px;
  border-radius: var(--r-full); background: var(--success-soft); color: var(--success);
  font-size: var(--fs-2xs); font-weight: 600; white-space: nowrap;
}
.pt-wa:hover { text-decoration: none; filter: brightness(.95); }
.pt-ext { display: inline-flex; align-items: center; gap: 4px; overflow-wrap: anywhere; }
.pt-notes { white-space: pre-line; overflow-wrap: anywhere; color: var(--ink-2); font-size: var(--fs-md); line-height: 1.6; }

/* ---- El formulario ---- */
.pt-form { display: flex; flex-direction: column; gap: var(--s3); }
.pt-form-sec {
  margin-top: var(--s2); padding-top: var(--s3);
  border-top: 1px solid var(--border);
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2);
}
.pt-form-sec:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.pt-checks { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); padding-top: 4px; }
.pt-ro {
  display: flex; align-items: center; min-height: 40px; padding: 0 12px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md);
  color: var(--ink-2);
}

@media (prefers-reduced-motion: reduce) {
  .pt-views .tab:active, .pt-kinds button:active { transform: none; }
}

/* ==========================================================================
   Equipo B2B · Agenda y Calendarios (0130)
   ========================================================================== */
.b2b-row { cursor: pointer; }
.b2b-row:hover td { background: var(--primary-soft); }
.b2b-cal.is-off { opacity: .7; }
.b2b-link .input { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: var(--fs-xs, 12px); }
.b2b-week { display: flex; flex-direction: column; gap: var(--s2, 8px); }
.b2b-day {
  display: grid;
  grid-template-columns: 9rem 1fr;
  align-items: center;
  gap: var(--s3, 12px);
  padding: var(--s2, 8px) 0;
  border-bottom: 1px solid var(--border, rgba(0,0,0,.08));
}
.b2b-day:last-child { border-bottom: 0; }
.b2b-day-name input { width: 18px; height: 18px; }
.b2b-day .input[type="time"] { width: 7.5rem; }
.b2b-second { display: inline-flex; align-items: center; gap: var(--s2, 8px); }
.b2b-second[hidden] { display: none; }
@media (max-width: 640px) {
  .b2b-day { grid-template-columns: 1fr; gap: var(--s2, 8px); }
  .b2b-day .input[type="time"] { width: 6.5rem; }
}
.b2b-next { width: 100%; text-align: left; padding: var(--s2) var(--s3); border-radius: var(--r-sm, 8px); border: 1px solid var(--border); background: none; color: inherit; font: inherit; cursor: pointer; }
.b2b-next:hover { background: var(--primary-soft); }
